利益相关:spring2022 spring2023 两届 head TA(也许明年还会再来)
首先简单总结一下今年(spring2023)的 CS100:
-
课程内容上,我们终于步入了 GCC12 + C17 + C++17 的时代,并且在顺序上也做了很多调整。
- 选择 C++17 的原因:众所周知 C++ 的三个大更新是 C++98, C++11, C++20,而 C++14/17 基本可以视为 C++11 的补丁,C++11 发展到 C++17 算是基本完善了。之所以不选择 C++20,一方面是编译器支持还不到位,我们无法编写、教授真正的 C++20-style code;另一方面 C++20 相比于 C++17 添加的东西实在有点复杂了,哪些该教哪些不该教?索性断了念想好。
- 顺序上的调整:将
string, vector, reference, range-for 这些东西放在 class 之前讲,将智能指针放在讲继承之前,并且将 modern C++ 的东西直接融入传统 C++ 的部分(例如 move),而不是单独放在最后作为 “高级主题”。这次的作业中除了 Dynarray 之外,所有的内存分配都由智能指针完成,课上的内容和考试题中的示例代码也都结合了智能指针,大家到 CS110 再好好体验手动管理内存吧。(没有对象怎么办?new 一个 std::make_unique 一个!)
- 内容上的调整:C++ 部分的 slides 几乎都重做了一遍。我对于往年的 slides 的评价是业余:顺序乱,内容落后于时代,而且每个部分都是浅尝辄止,没有谈到重点,并且示例代码中不正确、不标准、不推荐的写法也经常出现。特别地,这学期我做的所有 slides 都是直接对着 cppreference 甚至是 WG21 papers 做的,尽可能保证了内容的严谨性。一个遗憾是异常处理还是没塞进来。
-
作业上:hw2 和 hw3 的难度稍微大了一点,尤其是对刚开始学习的同学们可能确实不那么友好。如果可以重来的话,我可能会愿意放出更多的测试,或者以更友好的形式布置刚开始的这几次作业。C++ 部分的几次作业都有点拖时间了,尤其是 hw5 和 hw6,导致 hw8 时间实在是很紧张。为这些问题向大家道歉。另外 hw5 和 hw6 感觉各缺少一道编程题,代码量不是太够。
作业新增了客观题,这是因为每次作业就两三道编程题,有太多重要的知识点无法塞进这仅有的几道编程题里,还有很多关于写法的好坏的问题,有时候大家实现某些功能的写法其实是不推荐的、有隐患的,但我们无法在测试中体现。
作业还新增了和 TA 面对面 check 的环节,这是为了防止一些人使用 AI 或者抄袭 + 修改混过,同时也是为了我们能出一些更贴近课堂的题目,例如 Dynarray。我自己学 C++ 的时候,就是将《C++ Primer》书中的每一个例子都合上书独立地写过,事实上独立完成这样一些小的课堂例子是很有帮助的。
-
考试:真的不是故意出这么难的,题量也确实超出预期了,而且当时我们确实是有点上头了,没控制住。明年一定会好好控制考试的难度。真诚地向大家道歉。
-
习题课:这次所有习题课的内容都统一由我准备,并且我们特别选出了一些 senior TA,每个班都配一个 senior TA 和 1-2 个普通 TA。这是为了防止出现去年不同班级习题课差异太大、某些 TA 过于划水的情况。另外我还是非常愿意把我的习题课录下来传到 b 站的,但录制的效果可能不是很好,明年再改进。
今年习题课 slides 都变成了中文的,但保留了英文的术语和 reference,这是受到了南京大学 JYY 老师的操作系统课的启发。事实上我并不认为什么都用英语是一件多么优越的事情,开口就是英语是一件多么牛逼的事情。能把你用英语学的东西用中文讲清楚,才是真的牛逼。但学好英语绝对是很重要的,尤其是要适应全英文的学术研究和交流,以及英文的搜索引擎。越到后面好的中文资料就越少,没有办法。
再说说我来做 TA 的原因吧。先贴一段《C++ 沉思录》附录 “Koenig 和 Moo 夫妇访谈” 里的内容:
提问:你们二位对于现在的 C++ 教育状况怎么看?我们是否应该更加重视标准库教育,而不是语言细节的教育?或者你们有别的看法?
Koenig:当前 C++ 的教育状况实在太糟糕了。很多所谓的 C++ 教材不过是 C 语言书,只是在结尾粘贴一点点 C++ 的材料而已。结果呢,他们告诉读者,字符串乃是定长字符数组,应该用标准库中的 strcpy 和 strcmp 来操作。一个程序员一旦在一开始掌握了这些东西,就会根深蒂固,多年挥之不去。就其本身而言, C++ 是一种非常低级的语言。唯有利用库才能写出高层次的程序来。初学者还不能自己构造库,所以他们要么用现成的标准库,要么自己去写低层次的程序。确实有不少程序应该用低层次技术来构造,但是对于初学者不合适。
Moo:当然是库优于语言细节。两个原因:首先,学生们可以不必费力包装低层次的语言细节,从而更容易建立整体语言的全局观念,了解到其真实威力。根据我们的经验,学生们首先掌握如何使用程序库之后,就会很容易理解类的概念,学会如何构造类的技术。如果首先去学习语言细节,那么就很难理解类的概念及其功能。这种理解上的缺陷,使他们很难设计和构造自己的类。
不过,更重要的一点是,首先学习程序库,能够使学生培养起良好的习惯,就是复用库代码,而不是凡事自己动手。首先学习语言细节的学生,最后的编程风格往往是 C 类型的,而不是 C++ 风格。他们不会充分地运用库,而自己的程序带有严重的 C 主义倾向 —— 指针满天飞, 整个程序都是低层次的。结果是,在很多情况下,你为 C++ 的复杂性付出了高昂代价,却没有从中获得任何好处。
这本书的出版时间是非常早的(早于 C++98)。我不确定这个访谈的时间,但估计也就是在 2000 年前后。然而以上所提到的 “现在的 C++ 教育状况”,在今天仍然广泛地存在,而 C++ 已经发展到了第三个大版本,并且许多比 C++ 更 modern、更安全、更简单的语言如雨后春笋般涌现。如果你选择 C++,却按照 C++98 甚至 C with Classes 的方式学习、使用,那是完全不切实际的。上科大往年的 CS100 在国内众多高校的同类课程中不算是很差的,但正如那条评论所说:不要沉溺于比烂。我们往年的课程内容仍然存在大量的不合理、不合标准、落后于时代的地方,以及对于一些重难点的忽视。此外,C++ 是一门很复杂、很灵活、极易写错的语言,很多时候你会感觉好像写法 A 和写法 B 都能实现,而且可能写法 A 更符合你的直觉,但需要有人来告诉你为什么写法 B 更好、更不容易出错。这样的情况在 C++ 中经常出现,有很多经典的书籍就是在回答一个个这样的问题,比如 Scott Meyers 的著名的 Effective 系列。C++ 的教学也必须得有一部分这样的内容,不能因为这是除去 SI100B 之外的第一门编程课而去掉,这些内容不是难点,但是是 average students 应该掌握的重点。
我第一次有调整课程内容的想法,是我上个学期做 CS101 助教时看到 21 级很多同学的 programming assignments 的代码正如上面访谈中所述 —— 不会充分地运用库,而自己的程序指针满天飞。我感觉十分对不住 21 级的同学们,你们在 CS100 和 CS101 上都成了我们的小白鼠。
我们自己上过了这些课程,如果问有哪些地方不合理,能说出一二来的人不少,有心想要做出改变的人也不少。去年我做这门课的助教,当时只是怀揣着对 C++ 的热情,想要在作业和习题课里弄点真正有意思的东西。我最初想做助教的原因大概就是分享欲,我想要把这些我觉得很有意思的东西分享给更多的人,而如果我做了助教我就可以光明正大地 “夹带私货”。但事实上当你真的开始做这些工作,就会发现那些满足你分享欲的东西只占 20% 不到,剩下 80% 里你需要去讲数组和指针的各种运算、class 的成员怎么定义、STL 的各种函数等等这些很无聊的东西,还得理出一条合理的思路来让学生能听得明白,而且你最好在讲每个东西之前都去 cppreference 上重新学一遍,哪怕是你自认为很简单的数组、指针、函数。更重要的是,发自内心的 “分享” 变成了你每周要做的任务,你得按部就班地去完成。
作业也是如此。也许你写过不少有意思的程序,也经常有些很不错的 idea,或者你在你的研究中学了什么很有意思的东西,你也想夹带一下私货。但出作业不是在向学生炫耀你学过的东西,你需要考虑这两三周的课上学了哪些重点,应该配合什么样的题目和形式,还要考虑前后作业之间的联系,然后认认真真地去设计题面、写测试。很多人其实都有能力贡献一个好的 idea,但把它和课程实际情况联系起来,还要把题面和测试做好,这就有难度了。如果要把每一次作业的每一道题都设计好,就要花费更多的精力和时间。这些都不是光靠分享欲或者见到不合理之处想要改变的那种冲动就能完成的,它磨的是你的耐心和责任心。
也许今年花时间做了这些改变之后,明年能轻松一些吧。但去年做习题课 slides 的时候我也是这样想的,而今年我还是把习题课 slides 都重做了一遍。谁知道明年会不会又有什么新想法呢。欢迎有想法的同学明年来当 TA。