当你的技术栈与软工交集为空(x

很好你已经学会了 VueRustActixGitHub ActionspnpmVitestCaddy

现在你可以使用 ReactPythonDjangoGitLab CIyarnJestNginx 来完成软工作业了

技术栈交集为空的 meme

其实这里面比较有问题的就只有 React其他都还好只是数量多凑一点 meme 效果更好

小作业

Django 后端小作业

每一处需要修改的代码都列出来了还有详细的注释告诉你要干什么Django 完全没学就根据提示查了一处文档代码的整体逻辑也没搞清楚

感觉写完之后理解了 ChatGPT看着注释和示例补全代码根本就不需要学会如何写代码嘛

学 React

小作业应该不需要怎么学 React但还是把 Learn React (Beta) 完整过了一遍

之前都在 Twitter 上云 React学了之后终于有喜欢 Vue 的自信了所以说 X 自信就是要允许 Y 才能有以 X 自信为名打压 Y 到底是什么操作

React (Next.js) 前端小作业

上来就看到 ESLint 是 4 空格缩进优先双引号这能忍吗特意去确认了一下除了前端助教参与的几个项目随便找一个项目都是 2 空格缩进优先单引号

再一写代码发现不对劲这个 ESLint 有啥 rule 啊怎么怎么写都没 lint error给我整不会了

于是直接上了 @ouuan/eslint-config-ts理论上来说我应该整一个给 tsx 用的 config但 ts 的 config 配合上小作业模板原有的应该也凑合着能用吧

写完后的感觉和 Django 小作业差不多React 都白学了啥都不会就能写完

这是你前端小作业的最后一个 Step 了如果你已经完成了我相信你已经充分掌握了 Next.js 的入门知识

事实上这份前端小作业几乎可以作为大作业的起始框架除了 Next.js 框架本身其包含了

  • 代码风格检查与修正插件 ESLint配置文件为 .eslintrc.json
  • 单元测试框架 Jest

不是你是认真的吗先不谈学会多少能算是充分掌握了入门知识这个 eslintrc 真的能用吗

第二天早上起来再看了下代码发现组件 unmount 时没有 clearInterval而这需要在允许推荐的代码范围之外进行修改怎么回事

网络请求也是unmount 时没有 abort / ignore但要改的话交互逻辑也会有些变化就懒得修了一个简陋的小作业而已

CI/CD 小作业

前一天的 Power TUNA 上还有人问为什么 TUNA 有很多海外流量第二天就看到了在 Dockerfile 里硬编码 TUNA

为子目录设置 commit 邮箱

作业经常会需要或者说最好需要使用一些与平时不同的 commit 邮箱而 SECoder 的邮箱验证似乎还坏了就更需要了

以前碰到这种需求我都在每个 repo 设 local git config但在软工可能有好几个 repo不仅麻烦而且可能忘记就需要更好的解决方案

其实简单搜一下就很容易搜到毕竟这是个很常见的需求

  • ~/.gitconfig 中添加

    [includeIf "gitdir:~/some/path/**"]
        path = ~/some/path/.gitconfig
  • ~/some/path/.gitconfig 中添加

    [user]
        email = [email protected]

小作业的一些锅

deploy 之后发现一堆锅它们不影响我的小作业得分只会影响我能不能交上数学课作业但我还是修了数学课作业则是没写完就交了

说到这就得怀念程设训练了还有 5 分的课堂参与额外加在 100 分之外回答几个同学的提问开一些 issue 帮忙修锅就拿满了虽然最后这 5 分对 A+ 毫无帮助要是能移到软工就好了

Next.js static HTML export 有 dynamic route 时报错

在 Next.js 13.0.7 之前具体来说是 13.0.7-canary.5 之前通过 next export 得到 static HTML export 后如果访问一个能匹配上 dynamic route 的 static route会报Application error: a client-side exception has occurred例如pages/[id].tsxpages/list.tsx访问 /list.html 就会报错

简单看了一下这个版本的 changelog有几个疑似和这个 bug 相关的但我没能确认具体是哪个本来想在本地 build Next.js 来进一步确认但我一 build 就报一万个类型错误搞了半天也没搞好就放弃了反正 bump 一下就修好了开课前为啥不 bump 一下啊

Next.js static HTML export 的 Nginx 路由配置

感觉网上搜到的一些 Nginx 路由配置都很迷惑$uri 是匹配不到 HTML 文件的需要 $uri.html$uri/ 则可能匹配到目录导致 403动态路由如果不专门写路由配置的话就不能直接访问到正确的 HTMLstatic HTML export 的作用就没有了而且fallback 到 /index.html 可能导致加载一些不需要的页面内容和 JS实际上比直接 SPA 更劣

用户名格式检查

说来惭愧我一开始也没意识到用户名没校验格式的问题还是配路由的时候才想到用户名里会不会有 slash

现在要修的话确实麻烦所以只要归结为由于小作业的简化就好了

忘记关测试用 Docker container

第二天早上起来一看Plausible 特别卡再一看load avg 都快两位数了原来是在 VPS 上测试后端部署忘关了 🌚 不要随便在生产环境顺便测小作业

玩小作业

把 game of life 当成冬日绘板画画动态更新时钟从 LifeWiki 获取随机 pattern这是一个作业写不完的人能干的出来的吗共享后端是这样用的吗

第二天早上起来一看怎么每段都有个第二天早上起来大家都在画些啥我还是太保守了

回答同学提问

软工的公开提问貌似只能在微信群而且助教有十几个回复速度实在是太快了程设训练的时候我还能偶尔抢在助教之前回答问题现在根本做不到

偷窥同学代码

偶然间发现 SonarQube 上可以看到同学的代码因为我的小作业已经交了而且分都给了所以我就放心大胆地偷窥了

本来想给助教报告一下问题等权限修复结果说是懒得修了希望没多少人发现导致我甚至不能在迟交 ddl 之前在博客吐槽要是下学期还不修大家都学会了这个操作那只能说不是我的锅了那我只好趁机来认真看一看同学们都写了一些什么奇妙代码

  • 冗余的类型标注看到文档里讲 TS 的时候举例全是冗余类型标注时我就知道同学们肯定会写一万个 let count: number = 0

  • 只需条件修改 prop 时条件渲染 prop 不同的两个组件

  • 手写八遍而不是使用 for 来遍历网格的邻居

  • 更新 React state 时即使结果是常量依然使用回调函数

  • 回调函数写成 () => { foo(); } 而不是 foo

  • 冗余的 flex-direction: row

  • 复制二维数组有看到用 for 一个个 push也有看到直接 JSON.parse(JSON.stringify)正确写法应该是 old.map((row) => row.slice())数组大小为 1000x1000 时在 Firefox 中这两种写法的用时都大约是 map & slice 的 10 倍在 Chrome 中一个个 push 的用时是 map & slice 的 3 倍JSON.parse(JSON.stringify) 的用时是 40 倍而且由于小作业中需要的是复制其他所有但修改一个很多同学在 for 里面写 if这样效率更低应该把 if 写在 for 外面

    但是还看到一种写法只深复制修改了的那一行其他行浅复制这样确实性能更好

  • 依赖于效果为 toggle 的按钮不会在 toggle 完成前被点击两次

    • 问题背景一个 start 按钮和一个 stop 按钮修改一个 playing 的 state处于 playing 状态时需要一个 setInterval
    • 问题 1在 start / stop 时将 playing 修改为 !playing 而非 true/false
    • 问题 2只在 stop 时 clearInterval没有在 start 时 clearInterval

    正常的交互很难做到 toggle 完成前被点击两次基本上只能通过在 console 连续调用两次 click 实现但最好还是不要依赖于这一点

Node.js 和浏览器的不同 timer

队友问了一个神奇的 bug说是 clearInterval clear 不掉我看了半天都没发现问题最后发现开头有个 import { setInterval } from 'timers'

之前还真没注意过timer 有 Node.js 和浏览器两个版本Node.js 的 setInterval 返回的是一个 object浏览器返回的是一个 number

  • 直接写 setInterval在 TypeScript 中会被认为返回 NodeJS.Timer而实际运行时在哪运行就用哪个版本的函数
  • 如果写的是 window.setInterval在 TypeScript 中会被认为返回 number在 Node.js 中运行会报错
  • 如果是 import { setInterval } from 'timers'即使是在浏览器中运行也会使用 Node.js 版本的函数

这里比较重要的是 setIntervalclearInterval 要配套不能一个用 Node.js 的一个用浏览器的否则会 clear 不掉甚至报错

一般来说直接写window. 也不 import from 'timers'就是最好的虽然看起来 TypeScript 会将 number 误认为是 NodeJS.Timer但这个 number 本来就不该被当作一个 number 来使用这样的 typing 反而是好的

这里如果再仔细研究一下可以单独写一篇博客了但还是算了吧

小作业即将截止

小作业 将于 3 月 16 日周四23:59 截止

请注意截止时间不是 21:55

……

后面省略的几句也是模仿的 DSADNS 前几天某位助教答疑的时候把 dns typo 成了 dna DNA 动了好评但开头这个对偶的 ddl 绷不住了

大作业

组队

在另外一个通识课上体验了一下差点没组上队虽然后来得知还有不少人比我更晚组上队最后完全 rand 组队所以真的很感谢上学期就找我来组队的队友

起队名

HardToName / 起个名好难队

这是什么引用啊

队友提出了三个队名啊对对队BUG 全调队[redacted] 队前两个都被占了后一个太魔幻了于是最后还是用的我提出的队名lazy / 这个队特别懒什么都没留下~

这 SECoder 怎么还在用这个很有年代感的个人描述 placeholder 啊

学生列表,满屏都是“这个人特别懒,什么都没留下~”

俗话说得好贱名好养活取名叫 lazy 一定摆不起来

其实本来还想过利用五个人的名字缩写之类的组一个队名但人脑去想一个符合要求且有意思的队名太难了输入法给出的候选词也没啥意思所以我还尝试了用 ChatGPT 来生成本来只是以为它会生成一些没意思的队名没想到它生成出来的队名不仅没意思而且拼音首字母甚至字数都完全不符合要求无论怎么拷打都认错不改 🌚

分工 & 技术栈

听说代码可能要求有队友审核所以放弃了一个人写前端可能来个人写测试的想法

几乎是理所当然地就决定了用 Vue没有一点反对感觉这个不需要学 React 的 React 小作业没有九分也有十分的功劳

给队友布置学习任务的时候感觉我好像也不会多少东西像是前端的测试以及 Nuxt 都还得学JS/TS/Vue 说到底也就那么点东西我的优势可能主要还是在经验方面但其实也没写过什么复杂的前后端交互大作业和博客 / Codle 这种东西还是差别挺大写这个博客的时候很多时间也是花在一些 blog-specific 的不重要的细节上说的我都有点慌了

咕了一周的 Nuxt 3.3 终于在大作业开始前发出来了避免了刚开始写不久就要 bump minor versionyysy 我选的这些技术栈还是挺最新最热的要是真的出锅了都不知道怎么向队友交代

紧接着就看到 TypeScript 5.0 也发了更新更热了害怕

摇号

3月14日24:00后进行项目志愿的摇号

结果还真是24:00手动 ddl 🌚

本来晚上 11 点还看到我们队的一志愿的一志愿数量从 7 变成了 6就是 2/3 的概率抽上结果早上起来一看还是掉了这下和不是队友的室友一个选题了好在例会还是 4-3要是 4-4 的话整个下午就消失了

大例会 1

第一次例会竟然就要写分工以及完整的进度安排虽然说是随便画饼也没事但还是感觉不太敏捷

顺便练习了一下 Slidev在本机莫名 export 失败了结果扔到 VPS 上就成功了神秘但在 VPS 上还得装上中文字体并且配字体设置

无奖竞猜下面这些队名都是啥

下午的展示顺序是

  1. 蛋白质
  2. 对对对

感觉这个第一次例会总体上传达的意思就是看起来难的功能要想简单点差不多得了

大作业第一周

需求细化

第一次例会上是我提的问题最多之后也基本上只有我在群里问需求细节问题回答大部分都是两种之一要么是这样也可以但那样也可以要么是这样更好但没分程设训练的时候也是这样似乎是我的问题正常的想法是不是应该是只要不说清楚就可以混过去而不是害怕没搞清楚而写错

四个阶段

第一周总体上分成四个阶段

  1. 设计任务计划编写让队友知道要干什么的文档和 issue
  2. ping & push 队友
  3. 回答队友提问 & 指出队友代码里的问题
  4. 马上就要例会了放弃指导队友上手自己写

感觉最后总的工作量还是超过了自己一个人把所有活干完希望以后能好一点要一直是这样其他课真寄了而且我本来就没打算管后端就没学 Django结果不仅要搞一点后端的规划设计回答队友提问还得赶着 ddl 硬上写代码开发环境都没配好

数据库配置

你见过只能挂载目录不能设置环境变量也不能挂载单个文件的 Docker 容器管理吗

这个 SECoder 实在是有些过于离谱最后只能把环境变量写在 Dockerfile 里用 build 出来的数据库镜像

小例会 1

主要就是聊了一下数据库和 API 的设计也没检查 CI/CD结束之后才想起来架构设计也没说毕竟是小例会确实比较轻松感觉上午白着急把数据库跑起来了

大作业第二周

SECoder SSH 卡住

之前就偶尔碰到 SECoder SSH 卡住的情况今天发现是回了寝室连有线网就卡住换成 Tsinghua Secure 就不卡了怀疑和 IP 切换有关不是很懂

Nuxt 与 TypeScript 5.0

之前还说有点太新太热了果然一堆锅

之前一直随机报错 The "path" argument must be of type string. Received an instance of Array后来发现是我直接用了最新最热的 tsconfig 里 extends 写数组然后 Nuxt 读取 tsconfig 的时候寄了改成单个 extends 或者把 Nuxt 更新到 edge channel 就 ok 了

另外还碰到 一个 bug只能把路径改成英文

npmmirror 更新不及时

CI 挂在了奇怪的地方是 npmmirror 更新不及时一个刚更新几分钟的包下不下来npmmirror 的首页写的是每 10min 更新一次但我等了它半小时还没更新然后看到 npmmirror 上每个包的页面上有一个SYNC按钮点一下就可以更新

pnpm v8

感觉这个软工就和最新最热扯不开关系了

碰到一个非常神秘的一个 up-to-date with master 的 MR 在合并之后挂 CI说是 lock file 有问题本来我都没想管了结果晚上发现博客也挂 CI 了再一看原来是 pnpm 发布 v8 了

nuxt dev 报错 Body is unusable

Body is unusable (undici) · Issue #19245 · nuxt/nuxt 是一个非常玄学的 issue我在部署到 SECoder 的时候遇到了队友在 WSL2 上遇到了但我在本地Arch Linux没遇到过我让队友试着在 Docker 里跑 dev似乎和 issue 里描述的一样偶尔会遇到但重试一下就好了而且 WSL2 里加载非常慢直接在 Windows 上运行 Docker 会快很多

HMR 需要 WebSocket于是在 Docker 里跑 dev 的时候发现 Vite 默认的 ws 端口是 24678唤醒了一些远古的回忆结果去搜索引擎确认 自己的 DNA 没有刻错 的时候搜到的全是原神港口驶过几艘船二四六七八任务攻略绷不住了

大例会 2

例会前 CI 一直在排长队一开始还只用多等一会儿后来甚至会等待超时而直接挂掉差点没部署上

最后发现我们部署的 dev 环境可用 prod 环境不可用直接用的 dev 环境做演示没人问为什么地址里有个 dev后来发现确实是暴力改掉 migration 后数据库没重启的问题但我是一开始试图重启了但还是挂以为是其他问题但实际上是 SECoder 的容器重启需要等待而且不知道为什么有时候等好久也没重启成功非常玄学

其他队都看上去做了很多功能我们能演示的只有注册登录虽然我们的注册登录确实相对来说更加完善而其他队的其他功能也一堆问题但感觉在差不多得了的氛围下似乎还是赶上进度更重要

大作业第三周

说来实在是绷不住

我在一个未登录时返回 403 的 API 设置 CSRF cookie在前后端对接测试时发现这个 set-cookie 在经过前端 proxy 之后就没了于是我以为是 Nitro 的 proxy 不转发 set-cookie又马上要例会了就赶紧换成了 Nginx 反代

例会结束后我从 Nitro 源码翻到 h3 源码再翻到 undici 的 issue发现 Undici strips out set-cookie headers, even when "credentials: 'include'" is set又用 https://httpbin.org/cookies/set/cookie/test 进行测试发现真的没有 set-cookie还以为找到原因了但又发现 feat: remove headers filtering感觉很奇怪

于是我再仔细看了一下发现 https://httpbin.org/cookies/set/cookie/test 返回的是 302而重定向之后就没有 set-cookie而一开始那个 API 没有返回 set-cookie 则是因为它返回的不是 200改成 200 就正常了但凡我测试了一个返回 200 的也不至于..

上午因为这个问题差点没在例会前部署好例会后一直研究到晚上几乎是搞了一整天破防了

姓游就要用尤大的 Vueyóu だけにっ!

突然发现另一个队长姓游的队也用的 Vue而其他队暂时没发现有用 Vue 的我暂时只找到了 1/4 队伍的域名剩下有找不到的也有懒得找的难道是因为和尤大一样姓 yóu 吗这下爱姐狂喜了

undici 发送带 Content-Length: 0 的 DELETE 请求

这是第 114514 次被 undici 背刺了具体请看 Sending a DELETE request with "Content-Length: 0" fails with a RequestContentLengthMismatchError · Issue #2046 · nodejs/undici

而这个 Content-Length: 0 是由已经没在维护的 http-proxy 加上的不知为何甚至不是给其他 method 加 Content-Length 的时候忘记排除 DELETE 了而是专门给 DELETE 加的更神秘的是这段代码是在十年前只有一百多行的 initial commit 就加上了反正给这段打个 patch 就好了

SECoder commit 统计

之前还在想 SECoder 的数据统计什么时候开没想到一开吓一跳

它似乎是统计了所有 commit包括没 merge 到 master 的以及被 force-push 覆盖掉的结果我差不多到了 rk2 的两倍但要是只算 master 的话其实进 top10 都还差一点应该主要是搭前端代码框架的时候有 20 多个 commit rebase 了好几次后来也经常 force-push 修小的 typo这么说来 GitHub 只统计 master 还是挺好的虽然我个人项目也经常会在 master 上疯狂 force-push

但是 SECoder 没有 MR 评论数量的统计其实我觉得这个才是我应该霸榜的地方

大作业第四周

期中周事比较多稍微有点拖于是寄了

整体开发过程中存在大量开发进度不协调的问题前后端对接不协调开发新功能与审核测试之间不协调没有按测试需要的拓扑顺序进行开发导致先开发的功能要等着后面的功能才能测试对开发计划认识不统一还没修完当周计划的锅就开始写之后的功能……

我本来以为后端搭起基本框架之后我就不用管了可以让队友自己搞结果到了最后才发现全是锅虽然队友有各种奇妙操作但不得不说很多都是我可以提早发现来避免的还有很多是沟通上出了问题并且我自己的活也干得有点晚这毕竟是软工而不是大号程设训练只能承认我软工是真的菜做好规划安排以及与人沟通协作的基本能力非常欠缺

要是有万能的喵森来协调大家的开发进度就好了软工中的总集篇要是部署挂了赶紧换一个旧版镜像可以说是没写完而不是部署挂了就可以只扣 1 分而不是 2 分了 突然想到的但这么一想好想在软工结束后的暑假二周目一下白箱现在先拜一拜喵森吧

只不过还有一个问题Python 实在是真的能比 Rust 写的快吗虽然看队友写了很多奇妙错误但要是没有类型检查之类的Python 可以一定程度上检查但看起来队友并没有做我大概也能写出不少 🌚

大作业第五周

Nuxt v3.3.3 起 nuxt-vitest 报错

Nuxt v3.3.3 causes tests to fail (Unhandled Errors) · Issue #122 · danielroe/nuxt-vitest

想着大例会结束后是升级依赖的好时机结果一 bump 测试挂了去 git bisect 了一下 NuxtNuxt 的构建比 Next 轻松多了又快又不报错bisect 出来之后本来还在想没时间也没头绪继续研究下去了这个 issue 也已经一周了不知道作者会不会继续咕着结果晚上一看被点了个心开了个 PR再一看原来 bisect 出来的那个 PR 就是 nuxt-vitest 的作者写的我都没发现

NSpace 内 key 会失效

<n-space> 会给每个 child 套一个 <div>于是 key 都失效了如果在 <n-space> 里面用 v-for 就可能不停地 remount调了一晚上

这东西是真不如手写 flex

小例会 3

比较水只不过助教说他当年搞了个云服务器出问题了就把反代换成云服务器感觉很有道理

大作业第六周

大家这周都比较摆我还去修了不少后端的锅太久没管后端对代码复用测试的完善程度QuerySet 的编写请求参数的校验等问题感到了一些震惊但确实是没力气去修

响应式设计还作为自选需求被提了出来要是打算加这个需求一开始不就应该有吗这也不是什么需要由同学想到的功能我看需求列表没有就默认也不会作为自选需求了刚开课的时候还找助教吐槽没有响应式分数响应式设计要 mobile first能这么晚加吗

劝大家还是别太信需求列表该卷还得卷自己提自选需求总比快结束了被别人提强太多

大作业第 7~9 周

我有软工没有能加分的课为什么要打智能体

GIF 图片搜索网站

来点 PRJ2 笑话GIF 图片搜索网站每个队都是最后两三周才开始写搜索功能

大作业后面几周

没力气写游记了这个课快从世界上消失吧