原創|行業資訊|編輯:ZGL|2017-02-06 11:29:43.000|閱讀 1021 次
概述:考慮到計算機科學領域的廣闊增長,想要辨識現代計算機科學到底包含了什么,成為一件有挑戰性的事。每一個 CS 專業的學生應當知曉哪些事?我嘗試從四個方面來回答這個問題。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
考慮到計算機科學領域的廣闊增長,想要辨識現代計算機科學到底包含了什么,成為一件有挑戰性的事。
我們專業參與了這場辯論, 所以我整合了一下自己的想法來解答這個問題“每一個 CS 專業的學生應當知曉哪些事?”
我嘗試從四個方面來回答這個問題:
下面我會把自己的想法分為現代計算機領域的一般性原則和具體建議兩部分來寫。
計算機專業學生:請隨意把本文當作自學指南。
關于一些內容增刪的建議請郵件或聯系我。
更新:謝謝大家的建議和提醒!我一收到就會將其整理到文檔中保持隨時更新。
自從從工程學和數學分離出來之后,計算機科學行業就開始依靠簡歷來雇傭畢業生。
一份簡歷無法說明程序員的能力。
每一個計算機專業的學生都應當建立自己的作品集。
作品集可以像個人博客一樣簡單,上面有每個項目或成就的帖子。更好些的話每個項目有其單獨頁面和可供公共瀏覽的代碼(也許是托管到 Github 或者 Google Code 上)。
對開源代碼的貢獻應當給出鏈接和說明。
一份代碼作品集能夠使雇主直接評估雇員的能力。
而 GPA 和簡歷卻做不到。
教授應該設計課題來使作品集更出彩,學生在課程結束時應該花些時間做更新整理。
在計算機科學界“獨狼”已然成為瀕危物種。
當代計算機科學家必須練習與非程序員清晰且有說服力地表述自己的想法。
在小公司,程序員能否和管理層交流其想法能夠影響到公司的成敗。
不幸的是,為此單獨增加一個課程也并不能有什么改變(當然一個合理的科技交流課程沒有壞處)。
應當在課堂上提供給學生更多的機會來讓他們通過口頭講演的方式展示自己工作和想法。
我建議學生掌握一種演示工具,比如說 PowerPoint 或者(我最喜歡的)KeyNote。(抱歉,盡管我喜愛基于 LaTeX 的演示工具,它們還是過于靜態了)。
不過,要是想生成漂亮的數學文檔,LaTex 是無可比擬的。所有的技術課程的書面作業都應該以 LaTex 的形式提交。
計算機科學不是完全的工程學。
但也相差無幾。
計算機科學家們終會發現他們是和工程師相互合作的。
計算機科學家和傳統的工程師需要說相同的語言——一種扎根于實分析、線性代數、概率論與物理學的語言。
計算機科學家理應掌握物理學中的電磁學,但要達到這一點,他們還需掌握多元微積分(外加學習微分方程)。
在進行聲音仿真時,精通概率論和(通常還有)線性代數是極有益處的。在說明計算結果時,對統計學的深刻理解是無可替代的。
計算機科學家應當習慣并且熟練使用計算處理的Unix 哲學。
Unix 哲學(不同于 Unix 本身)是一種注重語言學抽象和整合來達到預期的效果。
在實踐中,這意味著要習慣于命令行形式處理、文本文件配置和輕型IDE的軟件開發。
考慮到 Unix 系統的流行度,當今的計算機科學家應當熟練地掌握基本的 Unix 能力:
學生在不理解 Unix 哲學的強大能力時會抵制它。此時最好讓學生嘗試完成一些 Unix 有相對優勢的有用的任務,比如:
一些計算機科學家嘲笑系統管理是一件“IT”任務。
他們的想法是他們可以自學技術人員能做得到的所有事。
這是正確的(理論上是)。
然而計算機科學家能夠完全且安全地控制他們的系統和網絡的這種態度是錯誤的。
軟件開發中很多任務不傳給系統管理員來做是最高效的。
每個當代的計算機科學家應當能夠:
編程語言的興起與衰落是有周期的。
而一個程序員的職業生涯不應如此。
盡管教授與獲得工作相關的語言很重要,學生能夠自學新的編程語言也同等重要。
學習怎樣學習新的編程語言的最好方式是學習多種編程語言和編程范例。
學習第n個語言的難度是第(n – 1)個的一半。
然而,要想真正理解編程語言,應該自己實現一個。理想情況下,每個CS專業的學生都參加過編譯課程。至少,每個學生應該實現一個注釋器。
下面的編程語言涵蓋了編程范例和實際應用:
Racket,作為功能全面的 Lisp 的方言,有著極簡單的語法。
對少部分的學生來說,這種語法是一種學習障礙。
不過坦率地講,如若學生覺得即使是暫時接受一種相異的語法規則也是很大的腦力障礙的話,他就缺乏從事計算機科學職業的靈敏心智。
Racket 豐富的宏系統和高階編程組件徹底打破了數據和代碼的分別。
如果教的合理,能夠充分發揮 Lisp 的魅力。
C 是對硅的簡潔至極的抽象。
C 在嵌入式系統的編程中無可替代。
學習 C 能提供對馮·諾依曼體系的深入理解,其程度沒有其他語言能比擬。
考慮到有缺陷的 C 編碼與普遍的緩沖區溢出安全隱患有著緊密的關系,程序員學習正確地編寫 C 程序是很重要的。
Javascript是動態、高級語言比如 Python、Ruby 和 Perl 的語義模型的一個很好的代表。
作為 web 原生語言,它的實用性優勢是獨一無二的。
Squeak 是最純正的面向對象語言 Smalltalk 的現代方言,它展現了“面向對象”的本質。
Java 將保持流行久到無法將其忽略。
Standard ML 是 Hindley-Milner 系統的一個干凈的體
Hindley-Milner 類型系統是現代計算領域最偉大(然而卻是最不知名)的成就。
盡管有著指數級的復雜性,Hindley-Milner 的類型推斷對于正常的程序來說是足夠快的。
類型系統支持復雜的結構化不變量表達,事實上,它豐富到類型定義良好的程序經常是沒有 bug 的。
盡管在應用上占有一席之地,邏輯編程是計算思維的另一種范例。
在程序員需要在其他編程范式里模擬邏輯編程時,理解邏輯編程是值得的。
另一種值得學習的邏輯編程語言是。miniKanren強調純粹(不允許堆砌)的邏輯編程。這個約束逐步形成了另一種風格的邏輯編程稱為關系程序設計,并且它授予Prolog程序通常不支持的屬性。
Scala 是定義良好的函數式與面向對象的融合語言。Scala 是 Java 應該做到的樣子。
建立于 Java 虛擬機之上,并兼容現存的 Java 代碼庫,Scala 最有可能成為 Java 的后繼者。
Haskell 是 Hindley-Milner 語言家族的王冠。
充分利用惰性求值,Haskell 是主流編程語言中最接近于純數學的。
C++ 是無法避免的災禍。
但是既然必須要教 C++,那就教全。
特別是,計算機科學專業的學生畢業時應該掌握模板元編程。
任何匯編語言都行。
既然 x86 很流行,它也可能很流行。
學習編譯器的最好方式便是學習匯編,因為匯編直觀地展示了高級代碼如何轉化為低級代碼。
計算機科學家應該理解產生式編程(宏編程);詞法(和動態)范圍;閉包;原型;高階函數;動態調度;子類型;模塊和函子還有不同于其他特定語法的單體語義概念。
計算機科學家必須要對形式邏輯及其證明有深刻的理解。代數操作和自然推理證明是處理例程任務的有力方法,歸納總結證明在構建遞歸函數時很有用處。
計算機科學家必須對形式數學記號很熟悉,并且對基本的離散數學結構——集合、元組、隊列、方法和冪集能進行嚴格的推理。
對于計算機科學家,掌握這些理論很重要:
學生應該學習足夠多的數論知識來研究和實現基本的加密協議。
學生應該必定見過常見(或者罕見但異常有效的)數據結構和算法。
但是,比起知道特定算法和數據結構(這些經常是很容易查閱到的),計算機科學家應該理解知道如何去設計算法(比如貪心算法、動態規劃策略等)并且知道如何將理想中的算法真正實現。
對于想獲得長期雇傭關系的計算機科學家來說至少要知道這些:
計算機科學家應該可以實現或者擴展操作這些數據結構的算法,包括增刪改查特定元素。
考慮到完備性,計算機科學家應該知道每個算法的指令式和函數式實現。
理解理論是在研究生院進行研究的先決條件。當能提供了一個問題的hard boundaries(或者是提供轉化為最初是hard boundaries的方法) 時理論是無價的。
計算復雜度可以說是所有計算機“科學”的真正的預測理論之一。
計算機科學家必須 知道易處理性和可計算性的程度,如果忽略了這些限制,最好的情況是有些挫折,最差的情況是導致失敗。
在本科階段,理論至少應涵蓋計算模型和計算復雜度。
計算模型應該包括有限狀態自動機、正則語言(和正則表達式)、下推自動機、上下文無關語言、形式文法、圖靈機、lambda 演算和不可判定性。
在本科階段,學生至少要學習足夠復雜的知識來理解 P、NP、NP-Hard 和 NP-Complete 的區別。
為了防止留下錯誤印象,學生應該通過將一些 NP 的問題簡化為
SAT并使用 SAT 求解程序求解。
對軟件架構有見識的理解是無可替代的。
計算機科學家應該從晶體管開始理解一個計算機。
架構的理解包含一些標準的抽象:晶體管、邏輯門、加法器、多路復用器、觸發器、算術邏輯單元、控制單元、緩存和隨機存取存儲器。
對高性能計算 GPU 模型的理解在可預知的未來是很重要的。
要想在現代系統上達到高性能對緩存、總線和物理內存管理的理解是很重要的。
要想理解機器架構,學生應該設計和仿真一個小的 CPU。
任何足夠大的程序最終都將成為一個操作系統。
正因如此,計算機科學家應該知道內核是如何處理系統調用、分頁、調度、上下文切換、文件系統和內部資源管理的。
對操作系統的理解僅次于對編譯器和實現高性能的架構的理解。
理解操作系統(我想當然也包括運行時的系統)在對嵌入式系統進行編程時是非常重要。
學生必須在一個真正的操作系統上動手實踐,在 Linux 和虛擬化技術的幫助下,這比之前容易些。
想要對內核有很好的理解,學生應該:
考慮到網絡的普遍性,計算機科學家應該對網絡棧和網絡中的路由協議有堅定的理解。
對計算機科學家來說,在不可靠傳輸協議(比如 IP)的基礎上構建可靠的傳輸協議(比如 TCP)的機制不應是不可思議的而應是核心知識。
他們應該理解在協議設計中的權衡——比如,什么時候選擇 TCP,什么時候選擇 UDP。(程序員需要知道在大型網絡中有阻塞,他們也應更大規模地使用 UDP。)
考慮到當代程序員進行網絡編程的頻繁性,理解現存協議標準是有用的:
計算機科學家應該理解包沖突時的指數回退和在擁塞控制中的加法增大和乘法減少機制。
每個計算機科學家應該實現:
要想通過網絡介紹課程,每個學生都應該使用wireshark來嗅探他們導師的谷歌搜索。
也許要求每個學生基于 IP 來從頭實現一個可靠的傳輸協議是有些強人所難了,但可以說這是我學生時代的一個對我個人改變很大的經歷。
一個傷感的事實是大多數安全漏洞都來源于粗心的編碼,更悲哀的事實是很多學校在訓練程序員編寫安全代碼上做的很不到位。
計算機科學家必須知道程序被攻破的方式。
他們需要形成防御型編碼的意識——考慮他們自己的代碼可能被攻擊的方式。
安全最好在整個課程體系中分布開來進行訓練:每個學科都應該提醒學生關于這個學科的原生漏洞。
每個計算機科學家至少應該了解:
一些讀者指出計算機科學家也應知道基本的 IT 安全措施,比如選擇合理的好密碼和使用 iptables 配置防火墻。
密碼學使得我們的大部分數字生活成為現實, 計算機科學家應該理解并能夠實現下面的概念,并且知道實現這些的常見陷阱:
在實現這些密碼系統時有個常見的錯誤——為手頭工作獲得 足夠 隨機的數,而這是每個計算機科學家都應該知道的。
最后,如此多的數據泄露表明,計算機科學家應該知道如何在存儲密碼時進行加鹽和哈希處理。
每個計算機科學家應該都有使用手工統計工具來破解使用前現代加密系統的密文的樂趣。
RSA 是容易實現的 ,每個人都應試試。
每個學生都應創建他們自己的數字簽名并在 apache 上建立 https 連接(做這個是出乎意料的費勁)。
學生還應該寫一個使用 SSL 進行連接的 web 客戶端。
作為實踐,計算機科學家應該知道如何使用 GPG、ssh 的公鑰認證、一個文件夾或者硬盤的加密。
軟件測試必須貫穿整個課程體系。一個軟件工程的課程可以涵蓋測試的基本風格,但是只有練習才能掌握這項藝術。
應該根據學生上交的測試實例來給他們打分。
我使用學生上交來的測試實例來對其他學生進行測試。
學生看起來并不很在意防御性的測試實例,但是當向他們的同學下手時卻毫不留情。
程序員大多是給其他程序員寫程序,或者更糟糕,給他們自己寫。
用戶接口設計(更寬泛的講是用戶體驗設計)可能是計算機科學最不受重視的方面。
即使是在專家之間也有這種誤解,即用戶體驗是一種無法被教授的“軟”技能。
在現實中,現代用戶體驗設計根植于人因工程學和工業設計中的人工經驗。
如果沒有別的辦法,計算機科學家至少應知道接口執行任何任務的難易程度應該與任務的頻率與重要性的乘積成比例。
為實用性考慮,每個程序員應該習慣于使用 HTML、CSS 和 Javascript 等設計可用的 web 接口。
好的可視化是可以將數據表現為人類可以感知的信息,而做到這點并不容易。
現代世界是數據的海洋,而開發人眼感知的局部最大值是理解這些信息的關鍵。
如今并行化比以往更落后、更難看。
不幸的是要掌握并行化需要對架構:多核、緩存、總線、GPU 等等有很深的理解。
并且需要練習,大量的練習。
并行化的“終極”答案還不得而知,但是一些領域特定的解決方案已經給出。
當下學生應該學習 CUDA 和 OpenCL。
線程是脆弱的并行化抽象,特別是引入緩存和緩存一致性之后。但是,線程很流行且微妙,所以值得學習,Pthread 是一個合理的輕量庫。
對于對大規模并行化感興趣的人來說,MPI是首要條件。
在理論上,map-reduce 是經久不衰的。
軟件工程的原理改變地和編程語言一樣快。
一個好的動手實踐的團隊軟件開發練習能夠展現出軟件工程的固有誤區并提供關于這些誤區的工作知識。 一些讀者建議說學生應該分為三人一組并且在不同的項目中輪流當組長。
學習如何與現存大代碼庫打交道是每個程序員的必備技能,并且最好是在學校而不是在工作中掌握此項技能。
所有的學生都應知道集中版本控制系統如 svn 和分布式版本控制系統如 git。
對于調試工具如 gdb 和 valgrind 的使用很長時間后會很有益處。
隨著對安全可靠軟件的需求提高,形式化方法也許將是開發這種軟件的唯一方法。
當前軟件的形式化模型和證明還很有挑戰性,但是這項領域的進程是穩健的:一年比一年容易。
也許在當前的計算機系學生的有生之年,形式化軟件開發能成為一種預期技能。
每個計算機科學家應至少熟練使用一種定理證明器(我認為具體是哪一種并不重要)。
學習使用定理證明方法能夠快速影響代碼風格。
比如說,一個人本能的不愿寫無法覆蓋所有可能性的 match 和 switch 語句。
再比如當寫遞歸函數時,使用理論證明方法的人有很強的欲望去消除 ill-foundedness。
再沒有一門學科比圖更能體現“聰明”。
這個領域是由“足夠好”驅動甚至由之定義的。
因此,沒有比圖形仿真更好的方式來教授巧妙的編程和進行性能優化。
我所學到的半數編碼技巧都來自于對圖的學習。
簡單的光線追蹤器可以在百行代碼內實現。
實現從 3D wireframe engine 獲取 3D 投影是要費些腦力的。
類似于 BSP 的數據結構以及類似于 z-buffer 渲染的算法是巧妙的設計的例子。
在圖形仿真領域,還有很多其他實例。
機器人是教授編程入門的最具吸引力的方式之一。
并且隨著機器人的價格持續走低,哪一款將引發個人機器人浪潮成為了門檻。
對于會編程的人來說,個人機器自動化的偉大時代即將來臨。
僅是考慮到對早期計算歷史的巨大影響,計算機科學家也應學習人工智能。
即使人工智能的最初夢想還遠未實現,人工智能在一些領域已有成效,比如機器學習、數據挖掘和自然語言處理等。
除開杰出的技術優點,對“relevance engineer”工作崗位需求的增大表示出每個計算機科學家都應該了解一下基本的機器學習。
機器學習也更加強調了理解概率論和統計的重要性。
在本科階段,核心概念應包括貝葉斯網絡、集群和決策樹學習。
數據庫十分常見和有用以至于人們常常忽略它。
理解支撐數據庫引擎的數據結構與算法是有益的,因為程序員經常需要在一個大的軟件系統中實現一個數據庫系統。
在sub-Turing 的計算模型的非凡的成功故事背后,關系代數和關系計算起了極大的作用。
比起 UML 模型,ER 模型更適于可視化編碼設計和約束的軟件設計。
計算機科學家可以設置和運行LAMP堆棧是一個好主意,遠離經營他們自己的公司需要大量艱苦的工作。
由于我自己也是有知識盲點的,所以上面這些建議也有一些局限性。
如果還有哪些應當包含但沒有列出來的東西,請大家在評論中補充。
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn