软工课小作业遇到的问题
小作业写完了,总结一下
软工虽然有文档但不多,因此记录一下踩过的坑,课程结束之后看看能不能报上去 写完小作业之后也与助教沟通了这些问题。
助教似乎想让我给文档仓库发 pr 直接修改文档里的问题,我想了想没有同意。这么回复的:
pr 意味着我要编写出合理的文档,并且一旦被合并,我就开始为文档的内容负责。在并不清楚会收获何种回报的前提下,我不愿意承担应由课程团队完成的工作。此外,我并不知道助教们对于我提的这些问题的看法和态度,这也使我无法 pr。
虽然似乎成为课程文档的 contributor 听起来很牛,但我还是想尽量避免背锅的。
环境配置部分 #
Miniconda 的安装 #
文档中提到,为 root 用户安装 Miniconda:
sudo bash Miniconda3-latest-Linux-x86_64.sh
然而,这会把 Miniconda 安装在 root 用户的 ~。因此,使用 VS Code Remote 开发项目时,由于使用普通用户权限执行,似乎无法识别到已经设置好的虚拟环境。我删掉之后用普通用户重装就十分顺利了。并且,对于不熟悉 Linux 的同学,直接让他们使用 root 用户进行各种操作并不合适。
后续:助教移除了文档中这里的 sudo。https://github.com/THUSE-Course/course-index/commit/7265b9fe081f849e39506c2dd33317204674a7d9
安装 uWSGI #
部署的时候会告诉你让你装 uWSGI,然而直接 pip install 在我的机器上(Ubuntu 22.04.2LTS, WSL 2)会由于 build wheel 的链接阶段出错而无法安装。网上有人给出了安装旧版 gcc 的方法,我并不敢尝试。后来查到的解决方案是先运行
conda install -c conda-forge uwsgi
pip install -r requirements.txt
就好了。
究其原因,conda-forge 频道里的包是预编译好的,不需要本地再构建一次了。
然而在构建 Docker 镜像的时候,能够直接使用 pip 依据 requirements.txt 装好依赖。原因是助教要求使用的 python:3.11 image 里包含了 gcc 4,符合版本要求。
后续:助教在这里加了 note。https://github.com/THUSE-Course/course-index/commit/cd342cf9e28aea6fa7d58bf48857a249acabc3bf
yarn 安装 tsc #
安装完之后似乎不会自动给你加环境变量,需要自己改一下 .bashrc。
后续:这个没反馈,感觉是小问题。
Docker #
花费时间最久的地方。
助教在文档中笼统地说:
在 Windows 和 macOS 下,你需要通过 Docker Desktop 来使用 Docker。不过,在 Windows 下更推荐的方法是通过 WSL 来使用 Docker。
这让我直接在 WSL 上安装了 Docker。然而,Docker 官方推荐的做法是直接安装 Docker Desktop,并且打开与 WSL2 集成的功能。这样更加便于管理。
我在 WSL 上安装的 Docker 无论如何都无法联网,即使连接了宿主机的代理也是一样。然而卸载后使用 Docker Desktop 重装,再连接宿主机的代理似乎就能正常 build 了,不知道为什么。
后续:助教加了 note。不过显然没有我这里写的这么细,只是丢了个官方文档让你看。https://github.com/THUSE-Course/course-index/commit/762dc888ad33b77bba091c3dca43c54807a4b8f5
Git #
小作业提交 #
与 Rust 课程中助教给每个人设置好了自己的仓库不同,小作业是从 Tsinghua Git 上拉取,然后推送到 SECoder Git 上。文档并没有说明如何设置。
首先查看当前仓库 remote 的信息:
git remote -v
origin git@git.tsinghua.edu.cn:se-2024fall/2024-next-hw.git (fetch)
origin git@git.tsinghua.edu.cn:se-2024fall/2024-next-hw.git (push)
我们需要修改的是 push 操作对应的 URL:
git remote set-url --push origin <NewURL>
后续:这个没反馈,感觉属于“基本技能”。
前端小作业 #
Step 4 #
本 Step 要求在未登录的时候要能够自动跳转至登录页面。为此,助教在 src/pages/index.tsx 中写了跳转的代码,并且置于一个 catch 块中:
const saveBoard = () => {
request(
"/api/boards",
"POST",
true,
{
userName,
boardName,
board: boardToString(board),
}
)
.then((res) => alert(res.isCreate ? CREATE_SUCCESS : UPDATE_SUCCESS))
.catch((err) => {
if (
err instanceof NetworkError &&
err.type === NetworkErrorType.UNAUTHORIZED
) {
alert(LOGIN_REQUIRED);
router.push("/login");
}
else {
alert(FAILURE_PREFIX + err);
}
});
};
关注这里的 18 和 19 行。助教的意图应该是,在负责网络请求的 request 函数中,学生需要补全的部分内,若无法获取 token,则抛出一个异常,然后在这里捕获,从而实现跳转。
然而实际上学生会发现,就算不在 request 需要补全的部分写任何东西,也能实现这一跳转功能。这是由于 request 已经写好了如下代码:
const data = await response.json();
const code = Number(data.code);
// HTTP status 401
if (response.status === 401 && code === 2) {
throw new NetworkError(
NetworkErrorType.UNAUTHORIZED,
"[401] " + data.info,
);
}
else if (response.status === 401) {
throw new NetworkError(
NetworkErrorType.CORRUPTED_RESPONSE,
"[401] " + data.info,
);
}
在将请求发送到后端后,后端会因为请求并未携带 token 而返回 401,从而在这里引发 request 抛出异常。在对接一个完好的后端进行测试时,无论是否按要求完成 request 的代码填空,页面的行为都几乎没有区别。
我认为应该在文档中强调,应在无后端的情况下进行这一测试。
后续:助教原话,“这里评分点是建立在完全完成后的 无论如何实现只要满足最后功能符合就可以 所以我倾向于这里不作更改”。