编者按:编程是确保在21世纪能立足的关键技能之一,但是在语言、框架、平台令人眼花缭乱的编程世界里,初学者应该学习什么样的语言和框架呢?如何才不会在这个黑森林中迷失自己呢?有10多年编程经验的后端工程师Vardan Grigoryan提供了很好的入门指导。尽管初级开发者基本上需要的是有好的问题解决技能,而且你的第一份工作不会要求你了解本文所有的东西,但是这篇文章对于你的职业生涯规划还是会起到很好的帮助作用。
我刚开始码农生涯的时候,主要的烦恼之一是语言/技术的选择问题。我应该学什么,应该从哪里开始?去找第一份程序员工作的时候应该了解什么?当时(10年前)还没有Coursera、 Udemy 或者 SoloLearn。我没法找到明确的方向,光靠自己没法找到通往成功就业的完整路径。这就是21世纪薪水高待遇好衣食无忧的宇航员工作:程序员。
这样的问题仍然存在:初学者仍然受困于选择,想要成为一名好的程序员没有康庄大道,而且社区对于“pythn是不是一门直觉语言??”这样的菜鸟问题也没有那么热心了。走向成功编程生涯的道路甚至比以往还要模糊。你应该在C++/C++11/C++14/C++17、Java、C#、Kotlin、PHP (什么?)、Python、Node.js、JavaScript(等一下,是用Angular、React还是Vue呢?)等等之间做出选择。
语言、技术还是技能?
为了回答你的主要问题,我必须先问你一个问题。你想要什么?你是对开发移动app感到兴奋呢,还是对网站或者Facebook这样的网站或者Medium这样的网站感兴趣?还是说你想开发一款像Photoshop那样的桌面应用?也许你想全情投入到游戏开发?是移动的还是桌面的呢?
回答“要想被技术公司聘为软件工程师我应该了解哪些东西?”的最明智方式是找出成功通过技术面试应该掌握的的主要技能。不过首先,我们应该把一些事情先理顺,来深入探讨一下编程的世界,看看里面都有哪些国家和城市,看看其中的文化和战争,看看个中的得与失。不过如果你性子就是这么急的话,直接往下翻到“准备编码面试”章节吧。
探索编程的世界把我们带到了3个主要平台面前:
Web(Google Search、Facebook、Amazon、Twitter等)
桌面(Dropbox、Photoshop、Visual Studio、Skype等)
移动(SoloLearn、Instagram、Uber等)
上述大多数服务在这三个平台都有。比方说Skype就是一个桌面、移动和web(虽然做得很糟糕)应用。Twitter是一个web和移动应用等等。
Web
在这个上下文背景下web本身就是一个很大的概念,为了讲清楚情况,我们会把他分成所谓的前端和后端,后者是我个人很喜欢的一块。前端是你看到的东西,后端是跑应用的服务器,负责处理用户请求、数据库请求等等。
前端。如果你希望掌握外观,比方说开发好看到让用户爱上的网站,你就应该了解HTML(样子),CSS(外观与感觉),JavaScript(感觉)。不过这还不够,利用纯粹的JavaScript在今天已经不够了,你必须选择合适的框架,比如目前流行的Angular、React和Vue。要选择哪一种主要取决于你最喜欢哪一家公司,是Google还是Facebook?如果你喜欢Google的话,那就用Angular,如果喜欢Facebook的话就用React。如果这两个你都不喜欢(很怪异),那就用Vue吧。简单!除了这些,你还应该掌握一些基本概念,比如HTTP协议的内部工作机制,要熟悉web服务器(至少不应该被Apache或者Nginx这样的名字吓着)。身为一名前端开发者意味着你从后端拿到要渲染(为了用户而装点)的数据,所以要对什么是API有最小限度的理解,对JSON(以及为什么它比XML好)的认知是必须的。(如果这些你都听得一头雾水的话,看看本文末尾的参考章节)。
dWeb上描述前端与后端差异的众多迷因之一。
后端。看不见的真相,未透露的故事。在过去,知道PHP足以自称为后端开发者,然后微软引入了ASP.NET。这两个就开始打架,直到Node.js冒出来把东西整理得井然有序。一些事件驱动开发的概念在Node.js上得到了最好的应用,所以如果你选择这个的话,你就是帮了你的项目大忙了。
后端令人困惑的一部分是语言的多样性,在后端你可以采用任何想要的语言,关键是,“后端”其实是“查询数据库、处理书、对客户端进行响应并且尽可能高效执行”的简称。,而选择“合适”的语言/技术/数据库并非选项。尽管一些开发者钟情MySQL或者PostgreSQL这类的关系数据库,但新进入者却选择黑暗面,NoSQL(比如Cassandra 或者MongoDB)。这个选择完全是个人的,但是我有一个简单的方程式。你有没有给你的数据制订严格的计划并且在不远的将来它都不会有太大的变化?如果是的话选择关系式数据库。你是不是每分钟的访问量超过了100万次?那就选NoSQL(很痛苦)。你的产品是不是频繁变更?那就选NoSQL。现在,假设你选好数据库,但是你又打算具体选择什么样的技术呢?你喜欢微软吗?有Windows Server吗?那就选MsSQL。你喜欢Oracle?那就选Oracle。你对Oracle没意见,但是很讨厌微软?选MySQL。你只是不想伤害任何人?那就选PostgreSQL吧。
NoSQL这玩意儿其实挺棘手的。这东西要取决于你的服务和数据架构。你得到的只是文档以及其中的一些弱连接?选MongoDB。你需要存储一大堆的键值对?选Redis。你正致力于类似图的结构(Facebook的朋友图谱,Google的知识图谱等)?选择Neo4j。其实你也不确定自己究竟想要什么,但是觉得这些全都需要?选ArangoDB吧。
数据库保存了所有的必要数据,但是你得客户端要想读/写该数据库却要你定义一个API。这里最有用的选项是Node.js,尽管你也可以用PHP或者ASP.NET、Ruby、Python,但我的个人推荐还是Node.js。好吧,Facebook后端用的是PHP,算是吧。他们用C++重写了PHP的很大一部分。一些人用Python而有的则喜欢用Ruby。诚然,你几乎可以用任何一种语言写后端,比方说Google用的是C++、Java和Python(以及Go)。对于底层的数据处理,C++是最合适的,对于像更新用户朋友推荐这样的后台任务,Java是一个好的选项。对于数据分析或者自然语言处理或者目前红得发紫额AI相关任务,你极有可能用的是Python。
再次地,后端除了各种语言、框架、数据库以外,你还需要掌握一些核心概念。
缓存(Caching)。从CPU缓存(有不同的级别)开始,到浏览器缓存结束,缓存无所不在。对于像Google Search或者Facebook这样的高负载服务来说,缓存是极其必要的。
服务器(Server)。你可能会认为这个跟硬件有关(如果你懂得如何设置几台服务器让它们成为一个整体去存储和处理数据的话当然很棒),不过对于后端开发者来说服务器意味着web服务器。当今流行的web服务器是Nginx,知道如何安装和配置这个玩意儿的话会对你今后大有裨益。
套接字(Sockets)。套接字是网络编程的基石。你通过网络发送/接收所有东西都是通过套接字进行的。了解套接字编程的底层细节对于你的技能军火库来说是非常有用的补充(知道TCP套接字、UDP套接字之间的区别,以及什么是WebSockets更是锦上添花)。
数据库设计。不管你选择了什么样的DBMS,对数据进行操作都会是你的主要任务之一。看清数据全貌,对数据进行可视化,并且将数据单元连接起来,这是你在编程生涯中需要掌握的一项技能。
安全。就像前面提到的其他概念一样,这个概念也非常宽泛。你无法彻底掌握其中的任何一种,所以至少你应该熟悉一些最佳实践,比如存储面哈希值而不是明文。通过API令牌检查请求,要对每一项请求验证用户许可等等。
桌面
我们会讨论桌面应用中令其成为桌面应用的那部分内容。在桌面平台上需要特殊技能组合的应用数不胜数,比方说,Photoshop处理的是图像,如果你想写类似Photoshop这样的东西的话,了解图像处理算法和技术就是必须。如果你想写类似Dropbox这样的东西,了解套接字编程就是必须。如果你想编写编译器或者类似Visual Studio这样的IDE,则知道如何设计编译器就是必须。具体细节这里就不谈了,我们就先探讨一下如果要做桌面平台的东西的话,你最有可能会用到的语言吧。
说到桌面应用的语言,开发者得在C++、Java或者C#之中做出艰难选择。不过这里有一个简单的公式帮你做出正确选择:如果你喜欢微软,用C#。如果你喜欢Oracle,用Java。如果你认为语言不应该从属于从何一家公司,用C++。如果这个的帮助作用不大,我们就讨论一下具体的子平台。如果你编写的软件只是给Windows用户用的,C#是最佳选择。理由很显然,这两个都是微软的产品,自然也会是最佳拍档。尽管C#的开发者坚称在发布了.Net Core之后,其实C#也可以用于Linux环境,但我个人建议是如果你也想覆盖Linux的话,那就用C++。其关键是,C++本身就是作为跨平台编程语言开发出来的,在所有操作系统中都表现得很好(是的,甚至在MacOS上)。在这个上下文中跨平台会假设你要把你的C++项目在各个操作系统中都要独立地进行编译,从而在具体的OS中交付“不同”的应用可执行文件。还有,说实话C++缺乏任何的GUI。实际上,这一点最大的借口可以说“C++是给铁杆开发者准备的,而铁杆开发者除了Terminal(命令行接口)以外什么都不用。”然而,一群很友好的开发者聚到一起开发出了Qt,这是完美适配C++的跨平台GUI库。
最后,如果你对C++的复杂性以及你得连接像Qt这样的独立库用户才能拥有完整的GUI体验感到愤怒,并且你讨厌要为不同的OS给你的产品编译和交付不同的可执行文件的话,那就用Java。Java有一个虚机,所以交付可执行文件很容易。你的应用在任何安装了JVM(Java虚拟机器)的OS都能工作得一样好。
移动
说到Java,第一个想到的东西就是Android。在Kotlin被引进之前很久时,Java是实现Android app事实上的标准语言。而在今天,Kotlin俘获了开发者的心,使得Android平台的应用开发体验变得更好。所以,如果你想要制作Android app的话,你应该在Java和Kotlin之间进行选择。为了做出正确的选择,我们应该看看幕后的东西。关键是,Google对Oracle不太感冒。Java是Oracle的,而Java统治着Google的Android,所以为了让自己有点灵活性,Google在明面上必须引入一个选项(或者在暗面上,这取决于你),而引入Kotlin的目的就是“哇哦,如果有这么个好东西的话为什么要用Java呢。”如果你刚开始你的Android开发者生涯的话,我个人建议你从Kotlin开始,尽管要想在市场上成为一名胜任的开发者,你必须支持此前已经用Java实现的app,所以,知道Java的话对你的简历会是个加分项。
最后是iOS。iLand完全是另一个故事。很长一段时间以来,Objective-C是iOS的统治性语言,而且说实话,掌握Objective-C需要非常认真,要有一些好耐性。这也是look开发者数量相对较少的主要原因之一,所以苹果最终做出了正确的选择,引入了Swift。Swift掌握起来要比Objective-C容易多了,这使得iOS的开发者数量出现了增加。所以,要想成为一名iOS开发者,你需要跟进Swift,但要想成为一名真正自信的开发者,建议你掌握Objective-C,从而为app(无数app都是用Objective-C写的)提供支持。
这里我还必须提一提React Native,因为它允许你只用JavaScript编写同时支持Android和iOS平台的app,然而,作为这个市场一个新的变化节奏很快的玩家,我们知道有这么一个东西,而如果你只知道JavaScript的话自己就能写简单的app了。
准备编码面试
在编程世界有些概念是基础。大多数技术面试的目的都是为了发现你的问题解决技能以及看看你是否了解那些概念,所以除了掌握一门编程语言之外,你应该熟悉一些在程序员军火库中必须的一些概念。
要想为编码面试做好成功准备,你应该对以下领域有自信:
算法与数据结构
计算机组织&操作系统
编码
系统设计
算法&数据结构
这是程序眼最迫切需要的技能集。以下是每一位程序员都应该熟悉的主题:
算法复杂性:大O的概念以及如何计算算法复杂性;基于复杂性知道哪一种算法更好,比方说O(N) vs O(logN)。
基本数据结构&适配器:数组、链接表、堆栈、队列。
排序&搜索:知道各种排序算法可帮助你识别项目的最佳的实现。作为练习,不妨试着实现以下插入排序选择排序或者合并排序,然后识别线性搜索与折半搜索的不同。
数&图:树和图无所不在,可以从Facebook的“朋友图谱”和Google Search的“知识图谱”开始。
哈希表:作为世界上最有效的数据结构之一,哈希表一直都是一个好选择。你应该能够实现一个哈希表并且熟悉解决冲突的技巧。
计算机组织&操作系统
强烈建议你要熟悉的主题包括:
逐位运算
CPU是如何执行机器代码的
RAM与动态RAM之间的区别时什么
有哪些类型的OS内核
“互斥”与“信号量”之间的区别是什么
什么是死锁,什么是活锁
编码
你应该至少对一门语言有着非常好的了解。要知道你喜欢的语言所有的优缺点,最佳实践,这有助于你写出优雅高效可读性强的代码。
高度推荐你通过解决有挑战性的问题来进练习,比如:
约瑟夫斯问题
汉诺塔
字符串压缩
平衡括号(Balanced Parenthesis)
孪生素数
系统设计
知道面向对象编程对现代程序员来说是必须的。
系统设计意味着要考虑整个系统,能够设计其架构、对其按类进行详细分析,定义对象的交互。
要准备好回答下述问题:
——让你设计Google Search的话你会怎么设计?如果每秒钟有数百万的并发请求该怎么办?
——你会如何去实现Facebook的朋友查找?
——为什么你需要使用关系式数据库管理系统?
——为什么你要使用NoSQL DB?
高度建议你了解和使用正确的设计模式。比方说,你应该知道Composite(组成)与Decorator(装饰)这两种结构型模式的不同。
尽管初级开发者基本上需要的是有好的问题解决技能,而且你的第一份工作不会要求你上述所有的东西都懂,但是这个列表对于你的职业生涯规划还是会起到很好的帮助作用。
原文链接:https://medium.com/sololearn/warning-your-programming-career-b9579b3a878b
编译组出品。编辑:郝鹏程。