每个计算机科学专业的学生都应该知道些什么?

每个计算机科学专业的学生都应该知道什么?

“每个计算机科学专业的学生都应该知道什么?”可以把这个问题作为四个问题的结合点来回答:
1.每个学生应该知道什么才能找到一份好工作?
2.要维持终身就业,每个学生都应该知道些什么?
3.进入研究生院应该知道什么?
4.每个学生都应该知道什么对社会有益?

投资组合与简历

从工程和数学毕业后,计算机科学专业采取了以简历为基础的方法来招聘毕业生。简历并不能说明程序员的能力。每个计算机科学专业的学生都应该建立一个作品集。作品集可以像个人博客一样简单,每个项目或成就都有一个帖子。一个更好的投资组合应该包括每个项目的页面和可公开浏览的代码(可能托管在github或谷歌代码上)。对开源的贡献应该被链接和记录。代码组合允许雇主直接判断能力。gpa和简历就不一样了。教授应该设计课程项目来给作品集留下深刻印象,而学生在每门课程结束时,应该花时间更新它们。

技术交流

计算机科学中的独狼是一种濒临灭绝的物种。现代计算机科学家必须有说服力地、清晰地向非程序员传达他们的想法。在小公司里,程序员是否能把自己的想法传达给管理层,可能会决定公司的成败。不幸的是,仅仅增加一门课程并不能解决这个问题(尽管一门扎实的技术交流课程不会有什么坏处)。更多的课程需要为学生提供机会来展示他们的作品,并通过口头陈述来捍卫他们的观点。

具体建议

我建议学生掌握一种演示工具,比如PowerPoint或(我最喜欢的)Keynote。(抱歉,尽管我很喜欢它们,但基于latex的表示工具太静态了。)在生成漂亮的数学文档方面,LaTeX无与伦比。所有技术课程的书面作业都应以LaTeX提交。

一个工程的核心

计算机科学并不完全是工程学。但是,已经足够接近了。计算机科学家会发现他们与工程师一起工作。计算机科学家和传统工程师需要讲同一种语言,一种植根于真实分析、线性代数、概率和物理学的语言。计算机科学家应该通过电磁学学习物理学。但是,要做到这一点,他们需要通过多元微积分(和微分方程的良好测量)。在构建声音模拟时,掌握概率和(通常)线性代数是非常宝贵的。在解释结果时,没有什么可以替代对统计数据的坚实理解。

Unix哲学

计算机科学家应该熟悉并实践Unix计算哲学。Unix哲学(与Unix本身相反)是一种强调语言抽象和组合以影响计算的哲学。实际上,这意味着要熟悉命令行计算、文本文件配置和无ide软件开发的概念。

具体建议

鉴于Unix系统的普及,计算机科学家今天应该精通基本Unix,包括以下能力:导航和操作文件系统;用管道组成流程;舒适地编辑文件与emacs和vim;为软件项目创建、修改和执行Makefile;编写简单的shell脚本。如果学生不理解Unix的强大功能,他们就会拒绝它。因此,最好让学生完成Unix具有相对优势的有用任务,例如:在给定的目录中查找占用最多空间的五个文件夹。在计算机上报告mp3的副本(按文件内容,而不是文件名)。取一个名字和姓氏都是小写字母的名单,并适当调整其资本结构。找出英语中所有以x为第二个字母,以n为倒数第二个字母的单词。直接将你的麦克风输入通过网络传送到另一台电脑的扬声器。为给定的目录用下划线替换文件名中的所有空格。报告来自特定IP地址的对web服务器的最后10次错误访问。

系统管理

一些计算机科学家嘲笑系统管理是一项“IT”任务。人们的想法是,计算机科学家可以自学技术人员能做的任何事情。这是正确的。(在理论上)。然而这种态度是错误的:计算机科学家必须能够胜任并安全地管理他们自己的系统和网络。软件开发中的许多任务无需经过系统管理员就可以高效地执行。

具体建议

每个现代计算机科学家都应该能够:安装和管理Linux发行版。配置和编译Linux内核。故障排除与挖掘、ping和traceroute的连接。编译和配置web服务器,比如apache。编译和配置一个类似于bind的DNS守护程序。使用文本编辑器维护web站点。切断和卷曲网络电缆。

编程语言

编程语言随着太阳周期的变化而变化。程序员的职业不应该如此。虽然教授与雇主相关的语言很重要,但学生学会如何自学新语言同样重要。学习如何学习编程语言的最好方法是学习多种编程语言和编程范例。学习第n种语言的困难是第n-1种语言困难的一半。然而,要真正理解编程语言,就必须实现一种语言。理想情况下,每个计算机科学专业的学生都应该参加一个编译班。至少,每个计算机科学专业的学生都应该配备一名口译员。以下语言提供了范例和实际应用的合理组合:
Racket;
C;
JavaScript;
Squeak;
Java;
Standard ML;
Prolog;
Scala;
Haskell;
C++; and
Assembly.

Racket语言

Racket作为一种功能齐全的Lisp方言,有着非常简单的语法。对于一小部分学生来说,这种语法是一种障碍。坦率地说,如果这些学生有一个基本的心理障碍来接受一个陌生的语法体系,即使是暂时的,他们缺乏在计算机科学的职业生涯中生存下来的心智灵活性。Racket
强大的宏系统和用于高阶编程的设备彻底消除了数据和代码之间的界限。如果教得正确,Lisp会解放。

C语言

C是对硅的简洁而无情的抽象。在嵌入式系统编程方面,C仍然是无可匹敌的。学习能以一种其他语言都无法做到的方式,对冯•诺依曼的主流架构给予深刻的理解。考虑到较差的C编程在缓冲区溢出安全漏洞的普遍存在中所起的密切作用,程序员学习如何正确地编程C是至关重要的。

JavaScript

JavaScript是流行于动态、高阶语言(如Python、Ruby和Perl)中的语义模型的良好代表。作为网络的母语,其语用优势是独特的。

Squeak

Squeak是Smalltalk的一种现代方言,是最纯粹的面向对象语言。它赋予了“面向对象”的本质。

Java

Java将继续流行太久而不能忽视它。

Standard ML

Standard ML是一个干净的体现后端-米尔纳系统。后端-米尔纳式系统是现代计算机领域最伟大(但鲜为人知)的成就之一。虽然复杂程度呈指数级增长,但对人类感兴趣的程序来说,后文-米尔纳的类型推断总是很快的。类型系统足够丰富,可以表达复杂的结构不变量。它是如此丰富,事实上,良好类型的程序通常是没有bug的。

Prolog

虽然逻辑程序设计在应用中很特殊,但它是计算思维的另一种范式。对于那些程序员可能需要在另一种范式中模拟它的实例,理解逻辑编程是值得的。另一种值得学习的逻辑语言是miniKanren。miniKanren强调纯(切不允许)逻辑编程。这个约束已经演化出一种被称为关系编程的逻辑编程风格,它授予Prolog程序通常不喜欢的属性。

Scala

Scala是函数式编程语言和面向对象编程语言的完美融合。Scala就是Java应该有的样子。它构建在Java虚拟机之上,与现有的Java代码库兼容,因此,它是Java最可能的继承者。

Haskell

Haskell充分利用了惰性,在任何主要编程语言的纯数学中都与编程最接近。

C + +

c++是一种必要的邪恶。但是,既然它必须被教授,它就必须被全面地教授。特别是,计算机科学专业的学生应该掌握甚至模板元编程。

Assembly

任何汇编语言都可以。因为x86很流行,所以最好是这样。学习编译器是学习汇编的最好方法,因为它让计算机科学家直观地了解高级代码将如何转换。

具体建议

计算机科学家应该理解生成编程(宏);词汇(和动态)范围;闭包;延续;高阶函数;动态调度;子类型化;模块和子;单子作为不同于任何特定句法的语义概念。

离散数学

计算机科学家必须对形式逻辑和证明有扎实的掌握。通过代数操作和自然推演的证明与常规编程任务具有相同的推理。归纳法的证明采用了递归函数构造的推理方法。计算机科学家必须精通形式数学表示法,严格地推理基本的离散结构:集合、元组、序列、函数和幂集。

具体建议

对于计算机科学家来说,很重要的一点是:
树木;图;正式的语言;和自动机。学生应该学习足够多的数字理论来学习和实现常见的密码协议。

数据结构和算法

学生当然应该看到常见的(或罕见的但不合理有效的)数据结构和算法。但是,比了解特定的算法或数据结构(这通常很容易查找)更重要的是,计算机科学家必须了解如何设计算法(例如,贪婪的动态策略),以及如何跨越算法的理想和实现的实质之间的差距。

具体建议

至少,寻求长期稳定就业的计算机科学家应该知道以下几点:哈希表;链表;树;二叉搜索树;有向图和无向图。
计算机科学家应该准备好实现或扩展对这些数据结构进行操作的算法,包括搜索元素、添加元素和删除元素的能力。为了完整起见,计算机科学家应该知道每种算法的强制性版本和功能性版本。

理论

掌握理论知识是研究生学习研究的先决条件。当理论在一个问题上提供了严格的界限时(或者当它提供了一种绕过最初看起来是严格界限的方法时),它是无价的。计算复杂性可以合法地声称是所有计算机“科学”中为数不多的真正预测理论之一。
计算机科学家必须知道可处理性和可计算性的界限在哪里。忽视这些限制会在最好的情况下招致挫折,在最坏的情况下招致失败。

具体建议

在本科阶段,理论至少应该涵盖计算模型和计算复杂度。计算模型应该包括有限状态自动机、正则语言(和正则表达式)、下推自动机、上下文无关语言、形式语法、图灵机、lambda演算和不可判定性。
在本科阶段,学生至少应该学习足够的复杂性来理解P、NP、NP- hard和NP- complete的区别。为了避免给学生留下错误的印象,学生应该通过减少SAT和使用现代SAT求解器来解决NP中的一些大问题。

体系结构

对计算机体系结构的扎实理解是无可替代的。计算机科学家应该从晶体管上理解计算机。
对架构的理解应该包括标准的抽象层次:晶体管、门、加法器、软线、人字拖、ALUs、控制单元、缓存和RAM。在可预见的未来,理解高性能计算的GPU模型将很重要。

具体建议

对缓存、总线和硬件内存管理的良好理解对于在现代系统上获得良好的性能至关重要。
为了更好地掌握机器架构,学生应该设计和模拟一个小CPU。

操作系统

任何足够大的程序最终都会成为一个操作系统。因此,计算机科学家应该知道内核如何处理系统调用、分页、调度、上下文切换、文件系统和内部资源管理。对操作系统的良好理解仅次于对编译器和实现性能的体系结构的理解。
在编写没有运行时系统的嵌入式系统时,理解操作系统(我将大量地将其解释为包括运行时系统)变得尤为重要。

具体建议

对学生来说,动手操作一个真正的操作系统是很重要的。有了Linux和虚拟化,这比以往任何时候都要容易。为了更好地理解内核,学生可以:在引导过程中打印“hello world”;
设计自己的调度器;修改页面处理策略;创建自己的文件系统。

网络

鉴于网络的普遍性,计算机科学家应该对网络中的网络堆栈和路由协议有一个明确的了解。在不可靠的传输协议(如IP)之上构建高效、可靠的传输协议(如TCP)的机制对计算机科学家来说并不神奇。它应该是核心知识。计算机科学家必须了解协议设计中涉及的权衡——例如,何时选择TCP,何时选择UDP。(程序员需要了解大规模使用UDP对拥塞的更大社会影响。)

具体建议

考虑到现代程序员接触网络编程的频率,了解现有标准的协议是很有帮助的,例如:
802.3和802.11;IPv4和IPv6;和DNS, SMTP和HTTP。计算机科学家应该理解包冲突分辨率的指数回归和拥塞控制中的加法-乘法-减法机制。
每个计算机科学家都应该实现以下目标:HTTP客户端和守护进程;一个DNS解析器和服务器; 命令行SMTP邮件程序。任何学生都不应该在通过初级网络课程时不嗅探他们导师的谷歌问题。要求所有的学生从头开始在IP上实现一个可靠的传输协议可能有点太过了,但我可以说,对我这样的学生来说,这是一次个人的变革性体验。

安全

安全的可悲事实是,大多数安全漏洞来自草率的编程。更可悲的事实是,许多学校在培训程序员确保代码安全方面做得很差。计算机科学家必须意识到程序被破坏的方法。他们需要培养一种防御性的编程意识——一种思考如何攻击自己代码的意识。安全是一种最好在整个课程中分布的培训:每个学科都应该警告学生其固有的弱点。

具体建议

至少,每个计算机科学家都需要了解:社会工程;缓冲区溢出;整数溢出;代码注入漏洞;竞态条件; 特权的困惑。
一些读者指出,计算机科学家还需要了解基本的IT安全措施,比如如何选择合法的好密码,以及如何使用iptables正确配置防火墙。

密码学

密码技术使我们的数字生活成为可能。计算机科学家应该理解并能够实现以下概念,以及实现这些概念的常见缺陷:对称密钥密码体制;公钥密码机制;安全哈希函数;质询-响应身份验证;数字签名算法;和阈值密码。由于这是加密系统实现中的一个常见错误,每个计算机科学家都应该知道如何为手头的任务获取足够的随机数。至少,正如几乎每一次数据泄露都表明的那样,计算机科学家需要知道如何对存储密码进行加密和哈希。

具体建议

每一个计算机科学家都应该享受使用手工统计工具破解前现代密码系统破解密文的乐趣。RSA很容易实现,每个人都应该这么做。每个学生都应该创建自己的数字证书,并在apache中设置https。(要做到这一点,难度惊人。)学生还应该编写一个通过SSL连接的控制台web客户机。
作为严格的实际问题,计算机科学家应该知道如何使用GPG;如何对ssh使用公钥身份验证;以及如何加密目录或硬盘。

软件测试

软件测试必须分布在整个课程中。一门关于软件工程的课程可以涵盖测试的基本风格,但没有什么可以替代实践的艺术。学生应该根据他们提交的测试用例来打分。我用学生提交的测试用例与其他所有学生进行对比。学生们似乎不太关心防御性测试用例的开发,但当涉及到向同学们扔沙袋时,他们就会大发雷霆。

用户体验设计

程序员经常为其他程序员编写软件,或者更糟,为他们自己编写软件。用户界面设计(或者更广泛地说,用户体验设计)可能是计算机科学中最不受重视的方面。甚至在教授之间也存在一种误解,认为用户体验是一种无法传授的“软”技能。在现实中,现代用户体验设计是建立在人类因素、工程设计和工业设计的经验主义基础上的。如果没有别的,计算机科学家应该知道,接口需要使执行任何任务的轻松程度与任务的频率乘以任务的重要性成正比。作为一种实用性,每个程序员都应该熟悉用HTML、CSS和JavaScript设计可用的web界面。

可视化

好的可视化是将数据以一种人类认为是信息的方式呈现出来。这不是一件容易的事。
现代世界是数据的海洋,利用人类感知的局部最大值是理解它的关键。

并行性

平行度又回来了,而且比以前更丑。不幸的事实是,利用并行需要对架构有深入的了解:多核、缓存、总线、gpu等等。而且需要实践和大量的练习。

具体建议

目前还不清楚并行编程的“最终”答案是什么,但已经出现了一些领域特定的解决方案。
目前,学生应该学习CUDA和OpenCL。线程对于并行性来说是一个脆弱的抽象,特别是当涉及到缓存和缓存一致性时。但是,线程是流行和棘手的,所以值得学习。Pthreads是一个值得学习的可移植线程库。对于任何对大规模并行性感兴趣的人来说,MPI是一个先决条件。
在原则方面,map-reduce似乎是持久的。

软件工程

软件工程中的原则变化速度与编程语言一样快。在团队软件构建的实践中,一个好的实践课程提供了关于工作中固有缺陷的工作知识。几位读者建议学生分成三个小组,由三个不同的项目轮流担任组长。学习如何攻击和操纵现有的大量代码库是大多数程序员必须掌握的技能,这是在学校而不是在工作中最好的学习方法。

具体建议

所有学生都需要了解像svn这样的集中版本控制系统和像git这样的分布式版本控制系统。gdb和valgrind等调试工具的工作知识在最终会对我们的工作大有帮助。

正式的方法

随着对安全可靠的软件需求的增加,正式的方法最终可能成为交付它的唯一手段。
目前,软件的正式建模和验证仍然具有挑战性,但该领域的进展是稳定的:它每年都变得越来越容易。在今天计算机科学专业的学生的一生中,甚至可能会有一天,正式的软件构建是一种预期技能。每个计算机科学家至少应该适度地使用一个定理证明程序。(我认为哪一个并不重要。)学习使用定理证明程序直接影响编码风格。
例如,一个人会本能地对写一个不能涵盖所有可能性的匹配或切换语句过敏。而且,在编写递归函数时,定理证明程序的用户强烈希望消除错误。

软件基础。

图形和模拟没有比图形学更被“聪明”所主导的学科了。这个领域被驱使着,甚至被定义为“足够好”。因此,没有比图形和模拟更好的方法来教聪明的编程或对优化工作有扎实的了解。我学到的编程技巧中有一半以上来自我对图形学的学习。

具体建议

简单的射线跟踪器可以在100行代码中构建。在线框图3D引擎中进行透视3D投影是很好的心理卫生。BSP树这样的数据结构和z-buffer呈现这样的算法都是聪明设计的好例子。在图形和仿真中,还有更多。

机器人

机器人技术可能是最吸引人的介绍编程的方法之一。此外,随着机器人技术成本的持续下降,人们正在通过一项门槛,这将引发一场个人机器人技术革命。对于那些会编程的人来说,难以想象的个人物理自动化程度即将到来。

人工智能

如果仅仅因为它对早期计算机历史的巨大影响,计算机科学家就应该研究人工智能。
虽然智能机器最初的梦想似乎还很遥远,但人工智能刺激了许多实践领域,如机器学习、数据挖掘和自然语言处理。

机器学习

除了其突出的技术优势外,“相关性工程师”职位空缺的数量表明每个计算机科学家都应该掌握机器学习的基本知识。机器学习加倍地强调对概率和统计的理解。

具体建议

在本科阶段,核心概念应该包括贝叶斯网络、聚类和决策树学习。

数据库

数据库太普通,太有用,不容忽视。理解为数据库引擎提供动力的基本数据结构和算法是很有用的,因为程序员经常在较大的软件系统中重新实现数据库系统。在计算的子图化模型中,关系代数和关系演算是非常成功的例子。与UML建模不同,ER建模似乎是一种可视化编码软件工件设计和约束的合理机制。

具体建议

一个计算机科学家,可以建立和操作一个灯泡堆栈是一个好主意和很艰苦的工作,而不是经营自己的公司。

欢迎关注我的微信公众号:AlbertYang
在这里插入图片描述

(文章来源http://matt.might.net/articles/what-cs-majors-should-know/)

猜你喜欢

转载自blog.csdn.net/qq_23853743/article/details/83870446
今日推荐