1.包括四个问题。如何找到一份好工作,如何维持终身就业,进入研究生院都应该知道什么,咋样才能造福社会。(来自转载)
2.投资组合与简历
从工程和数学中脱颖而出,计算机科学项目采用基于简历的方法来招聘毕业生。
应建立一个作品集。
作品集可以像个人博客一样简单,每个项目或成就都有一篇文章。更好的投资组合将包括每个项目的页面和可公开浏览的代码(可能托管在 github 或 Google 代码上)。
对开源的贡献应该被链接和记录。
代码组合允许雇主直接判断能力。
3.技术交流
计算机科学中的独狼是濒临灭绝的物种。
现代计算机科学家必须以有说服力和清晰的方式向非程序员传达他们的想法。
在较小的公司中,程序员是否可以将她的想法传达给管理层可能会决定公司的成败。
我们应该展示自己的作品并通过口头陈述来捍卫自己想法。
4.工程核心
计算机科学并不完全是工程学,但是二者很相近。
二者在一起工作。计算机科学家和传统工程师需要说同一种语言——一种植根于实分析、线性代数、概率和物理学的语言。
计算机科学家应该通过电磁学来研究物理学。但是,要做到这一点,他们需要通过多元微积分(和微分方程来衡量)。
在构建声音模拟时,掌握概率和(通常是)线性代数是非常宝贵的。在解释结果时,无法替代对统计数据的扎实理解。
5.Unix 哲学
计算机科学家应该熟悉并实践 Unix 的计算哲学。
Unix 哲学(相对于 Unix 本身)是一种强调语言抽象和组合以实现计算的哲学。
在实践中,这意味着要适应命令行计算、文本文件配置和无 IDE 软件开发的概念。
具体建议
鉴于 Unix 系统的流行,今天的计算机科学家应该精通基本的 Unix,包括以下能力:
导航和操作文件系统;用管道组成流程;使用emacs 和 轻松编辑文件vim;为软件项目创建、修改和执行 Makefile;编写简单的 shell 脚本。
除非学生了解它的力量,否则他们会拒绝 Unix 哲学。因此,最好挑战学生完成 Unix 具有比较优势的有用任务,例如:
查找给定目录中占用空间最多的五个文件夹。
报告计算机上重复的 MP3(按文件内容,而不是文件名)。
列出名字和姓氏都小写的名字,并适当地对其进行大写。
找出所有x第二个字母和n倒数第二个字母的英语单词。
通过网络将您的麦克风输入直接路由到另一台计算机的扬声器。
用下划线替换给定目录的文件名中的所有空格。
6.系统管理
计算机科学家必须能够胜任和安全地管理他们自己的系统和网络。
软件开发中的许多任务无需通过系统管理员即可最有效地执行。
具体建议
每个现代计算机科学家都应该能够:安装和管理 Linux 发行版。
配置和编译 Linux 内核。
排查连接 dig, ping和 traceroute。
编译和配置像 apache 这样的 Web 服务器。
编译和配置一个 DNS 守护进程,比如 bind。
使用文本编辑器维护网站。
7.编程语言
虽然教授与雇主相关的语言很重要,但学生学习如何自学新语言同样重要。
学习如何学习编程语言的最好方法是学习多种编程语言和编程范式。
学习第n种语言的难度是第 ( n-1 )种语言的一半。
然而,要真正理解编程语言,就必须实现一种。理想情况下,每个计算机科学专业的学生都会参加编译器课程。至少,每个计算机科学专业的学生都应该实现一个解释器。
8.标准机器学习
标准 ML 是 Hindley-Milner 系统的简洁体现。
Hindley-Milner 类型系统是现代计算中最伟大(但鲜为人知的)成就之一。
尽管复杂性呈指数级增长,但 Hindley-Milner 中的类型推断对于人类感兴趣的程序来说总是很快的。
类型系统足够丰富,可以表达复杂的结构不变量。事实上,它是如此丰富,以至于类型良好的程序通常是没有错误的。
9.序言
虽然在应用程序中是利基市场,但逻辑编程是计算思维的另一种范式。
对于程序员可能需要在另一个范式中模拟它的那些实例,理解逻辑编程是值得的。
另一个值得学习的逻辑语言是miniKanren。miniKanren 强调纯逻辑编程。这种约束已经演变出另一种逻辑编程风格,称为关系编程,它赋予了 Prolog 程序通常不具备的属性。
10.ISO C++
C ++是必要的邪恶。
但是,既然必须教,就必须全面教。
尤其是计算机科学专业的学生,在离开时甚至应该掌握 模板元编程。
11.部件
学习编译器是学习汇编的最佳方式,因为它可以让计算机科学家直观地了解高级代码将如何转换。
具体建议
计算机科学家应该了解生成式编程(宏);词汇(和动态)范围;关闭;延续;高阶函数;动态调度;子类型;模块和函子;和 monads 作为语义概念,不同于任何特定的语法。
12.离散数学
计算机科学家必须牢牢掌握形式逻辑和证明。通过代数操作和自然演绎的证明涉及常规编程任务常见的推理。归纳证明涉及用于构造递归函数的推理。
计算机科学家必须精通正式的数学符号,并严格推理基本的离散结构:集合、元组、序列、函数和幂集。
具体建议
对于计算机科学家来说,涵盖以下方面的推理很重要:树木;图表;正式语言;和自动机。
学生应该学习足够的数论来研究和实施常见的密码协议。
13.数据结构和算法
学生当然应该看到常见的数据结构和算法。
但是,比了解特定算法或数据结构(通常很容易查找)更重要的是,计算机科学家必须了解如何设计算法(例如,贪婪、动态策略)以及如何跨越算法与理想及其实施的本质。
具体建议
至少,寻求稳定长期工作的计算机科学家应该了解以下所有内容:
哈希表;链表;树木;二叉搜索树;和有向图和无向图。
计算机科学家应该准备好实现或扩展在这些数据结构上运行的算法,包括搜索元素、添加元素和删除元素的能力。
为了完整起见,计算机科学家应该知道每个算法的命令式和函数式版本。
14.理论
掌握理论是研究生院研究的先决条件。
当理论为问题提供硬边界时(或者当它提供一种规避最初看起来是硬边界的方法时),理论是无价的。
计算复杂性可以合理地声称是所有计算机“科学”中为数不多的真正预测理论之一。
计算机科学家必须知道易处理性和可计算性的界限在哪里。忽略这些限制在最好的情况下会导致挫败感,在最坏的情况下会导致失败。
具体建议
在本科阶段,理论至少应涵盖计算模型和计算复杂性。
计算模型应涵盖有限状态自动机、正则语言(和正则表达式)、下推自动机、上下文无关语言、形式语法、图灵机、lambda 演算和不可判定性。
在本科阶段,学生至少应该学习足够的复杂性来理解 P、NP、NP-Hard 和 NP-Complete 之间的区别。
为了避免留下错误的印象,学生应该通过减少到 SAT 和使用现代 SAT 求解器来解决 NP 中的一些大问题。
15.建筑学
对计算机体系结构的扎实理解是无可替代的。
计算机科学家应该从晶体管开始理解计算机。
对架构的理解应该包括标准的抽象级别:晶体管、门、加法器、多路复用器、触发器、ALU、控制单元、高速缓存和 RAM。
在可预见的未来,了解高性能计算的 GPU 模型将非常重要。
具体建议
对高速缓存、总线和硬件内存管理的良好理解对于在现代系统上实现良好性能至关重要。
为了更好地掌握机器架构,学生应该设计和模拟一个小型 CPU。
16.操作系统
任何足够大的程序最终都会成为操作系统。
因此,计算机科学家应该了解内核如何处理系统调用、分页、调度、上下文切换、文件系统和内部资源管理。
对操作系统的良好理解仅次于对实现性能的编译器和体系结构的理解。
在对没有操作系统的嵌入式系统进行编程时,理解操作系统(我会宽泛地解释为包括运行时系统)变得尤为重要。
具体建议
让学生亲身体验真正的操作系统是很重要的。使用 Linux 和虚拟化,这比以往任何时候都容易。
为了更好地理解内核,学生可以:
在启动过程中打印“hello world”;
设计自己的调度器;
修改页面处理策略;和
创建自己的文件系统。
17.联网
鉴于网络无处不在,计算机科学家应该对网络中的网络堆栈和路由协议有深刻的理解。
在不可靠的传输协议(如 IP)之上构建高效、可靠的传输协议(如 TCP)的机制对计算机科学家来说不应该是魔法。应该是核心知识。
计算机科学家必须了解协议设计中涉及的权衡取舍——例如,何时选择 TCP 以及何时选择 UDP。(如果程序员也大规模使用 UDP,他们也需要了解拥塞对社会的更大影响。)
具体建议
鉴于现代程序员遇到网络编程的频率,了解现有标准的协议会很有帮助,例如:
802.3 和 802.11;
IPv4 和 IPv6;和DNS、SMTP 和 HTTP。
计算机科学家应该了解数据包冲突解决中的指数回退以及拥塞控制中涉及的加法-增加-乘法-减少机制。
每个计算机科学家都应该实现以下内容:
HTTP 客户端和守护进程;
DNS解析器和服务器;和
命令行 SMTP 邮件程序。
18.安全
安全的可悲事实是,大多数安全漏洞来自草率的编程。更可悲的事实是,许多学校在培训程序员保护他们的代码方面做得很差。
计算机科学家必须了解程序可能被破坏的方式。
他们需要培养一种防御性编程意识——一种思考他们自己的代码可能会如何受到攻击的思维。
安全是一种最好分布在整个课程中的培训:每个学科都应该警告学生其自身的漏洞。
具体建议
至少,每个计算机科学家都需要了解:
社会工程学;
缓冲区溢出;
整数溢出;
代码注入漏洞;
比赛条件;和特权混乱。
一些读者指出,计算机科学家还需要了解基本的 IT 安全措施,例如如何选择合法好的密码以及如何使用 iptables 正确配置防火墙。
19.密码学
密码学使我们的数字生活成为可能。
计算机科学家应该理解并能够实现以下概念,以及这样做的常见陷阱:
对称密钥密码系统;
公钥密码系统;
安全散列函数;
质询-响应认证;
数字签名算法;
和阈值密码系统。
由于这是密码系统实现中的常见错误,因此每个计算机科学家都应该知道如何为手头的任务获取足够的随机数。
至少,正如几乎所有数据泄露所表明的那样,计算机科学家需要知道如何对密码进行加盐和哈希处理以进行存储。
具体建议
每个计算机科学家都应该乐于使用带有手动统计工具的前现代密码系统来破解密文。
RSA 很容易实现 ,每个人都应该这样做。
每个学生都应该创建自己的数字证书并在 apache 中设置 https。(这样做非常困难。)
学生还应该编写一个通过 SSL 连接的控制台 Web 客户端。
作为严格的实际问题,计算机科学家应该知道如何使用 GPG;如何对 ssh 使用公钥认证;以及如何加密目录或硬盘。
20.软件测试
软件测试必须分布在整个课程中。
软件工程课程可以涵盖测试的基本风格,但没有什么可以替代艺术实践。
学生应该根据他们提交的测试用例进行评分。
我使用学生提交的测试用例来对抗所有其他学生。
学生们似乎不太关心开发防御性测试用例,但是当涉及到对同学进行沙包时,他们会释放地狱。
21.用户体验设计
程序员经常为其他程序员编写软件,或者更糟的是,为自己编写软件。
用户界面设计(或更广泛地说,用户体验设计)可能是计算机科学中最被低估的方面。
即使在教授中,也存在一种误解,即用户体验是一种无法教授的“软”技能。
实际上,现代用户体验设计基于人因工程和工业设计的经验性原则。
如果不出意外,计算机科学家应该知道接口需要使执行任何任务的难易程度与任务的频率乘以其重要性成正比。
实际上,每个程序员都应该熟悉使用 HTML、CSS 和 JavaScript 设计可用的 Web 界面。
22.可视化
良好的可视化是以人类将其视为信息的方式呈现数据。这不是一件容易的事。
现代世界是数据的海洋,利用人类感知的局部最大值是理解它的关键。
23.并行性
并行性又回来了,而且比以往任何时候都更丑陋。
不幸的事实是,利用并行性需要深入了解架构:多核、缓存、总线、GPU 等。
还有,练习。多练习。
具体建议
目前还不清楚并行编程的“最终”答案是什么,但已经出现了一些特定领域的解决方案。
目前,学生应该学习 CUDA 和 OpenCL。
线程是并行性的脆弱抽象,尤其是在涉及缓存和缓存一致性时。但是,线程很流行,也很棘手,所以值得学习。Pthreads 是一个可移植的线程库,值得学习。
对于任何对大规模并行感兴趣的人来说,MPI 是一个先决条件。
在原则方面,map-reduce 似乎确实是持久的。
24.软件工程
软件工程原理的变化与编程语言一样快。
团队软件构建实践中的一门良好的实践课程提供了对工作中固有的陷阱的工作知识。
几位读者建议学生分成三人一组,领导者的角色轮流完成三个不同的项目。
学习如何通过现有的大型代码库进行攻击和操纵是大多数程序员必须掌握的技能,而且最好在学校而不是在工作中学习。
具体建议
所有学生都需要了解像 svn 这样的集中式版本控制系统和像 git 这样的分布式版本控制系统。
当它们最终变得必要时,像 gdb 和 valgrind 这样的调试工具的工作知识会大有帮助。
25.形式化方法
随着对安全、可靠软件的需求增加,形式化方法有一天可能最终成为交付它的唯一手段。
目前,软件的形式化建模和验证仍然具有挑战性,但该领域的进展是稳定的:每年都在变得更容易。
在当今计算机科学专业的学生的一生中,甚至可能有一天,正式的软件构建是一项预期的技能。
每个计算机科学家都应该至少适度地使用一个定理证明器。(我认为哪一个并不重要。)
学习使用定理证明器会立即影响编码风格。
例如,一个人本能地对写一个不涵盖所有可能性的陈述match或switch陈述感到过敏。
而且,在编写递归函数时,定理证明者的用户有强烈的消除无根据的冲动。
26.图形和模拟
没有比图形更受“聪明”支配的学科了。
该领域被驱动,甚至被定义为“足够好”。
因此,没有比图形和模拟更好的方法来教授聪明的编程或对优化工作的深入了解。
我学到的编码技巧中有一半以上来自我对图形的研究。
具体建议
只需不到 100 行代码即可构建简单的光线追踪器。
计算线框 3D 引擎中执行透视 3D 投影所需的转换是一种良好的心理卫生。
BSP 树之类的数据结构和 z 缓冲区渲染之类的算法是巧妙设计的绝佳示例。
在图形和模拟方面,还有很多。
27.机器人技术
机器人技术可能是教授入门编程最吸引人的方式之一。
此外,随着机器人技术的成本持续下降,门槛正在被超越,这将使个人机器人技术革命成为可能。
对于那些可以编程的人来说,难以想象的个人物理自动化程度即将到来。
28.人工智能
如果仅仅是因为它对早期计算历史的巨大影响,计算机科学家应该研究人工智能。
虽然智能机器的最初梦想似乎遥不可及,但人工智能催生了许多实用领域,例如机器学习、数据挖掘和自然语言处理。
29.机器学习
除了突出的技术优势外,“相关工程师”的大量职位空缺表明每个计算机科学家都应该掌握机器学习的基础知识。
机器学习双重强调理解概率和统计的必要性。
具体建议
在本科阶段,核心概念应包括贝叶斯网络、聚类和决策树学习。
30.数据库
数据库太常见也太有用了,不容忽视。
了解支持数据库引擎的基本数据结构和算法很有用,因为程序员经常在更大的软件系统中重新实现数据库系统。
关系代数和关系演算在亚图灵计算模型中脱颖而出,成为非凡的成功案例。
与 UML 建模不同,ER 建模似乎是一种合理的机制,用于可视化对软件工件的设计和约束进行编码。
具体建议
可以设置和操作 LAMP 堆栈的计算机科学家是一个好主意,而且除了经营自己的公司之外还需要大量的艰苦工作。