本篇博客是《软件开发者成长完全攻略》系列翻译文章第 2 章。
原文地址:The Technical Skills You Need to Have as a Software Developer
我更倾向于帮助程序员学习“软技能”而非开发技术 —— 事实上,我写过一整本关于软技能的书 —— 但是毫无疑问的,对于开发者来说,技术很重要!
我的意思是,如果你没有掌握代码和开发技术,所有的软技能对你来说都不会有实质上的帮助。或许你可以成为一个好的管理者或者教练,但不会是一个好的软件开发者。
既然你正在阅读这本书的这一小节,我可以假定你就是想成为软件开发者 —— 或者是优秀的软件开发者 —— 那就让我们讨论下你所需要掌握的技术。
值得学习的技术
让我事先声明,这一章的内容可能会吓退很多初学者,因为他们会觉得到要学习的内容太多了,甚至他们会感觉无从下手。
我会在这里试着把那些能让你在追求软件开发的路上受益最多,最值得学习的技术进行分解。本章不是为了列举你成为开发都可能会需要用到的所有技术,而是要列出那些最核心、最有价值的技术,并对他们进行一个概述。
不要慌。在这本书的另一个小节“软件开发所要掌握的技能”中,我会为下面列举的几乎所有技术各开一章进行详细的讲解。
我同时还将这本书浓缩到一个有用的工具 —— 软件开发技术评估 —— 中,你可以在这里进行下载。
所以,话不多说,以下就是针对我觉得最重要的技术的概述。
一门编程语言
我觉得每个人都是从这一点开始的。
如果不掌握一门编程语言,是不可能真正成为一个程序员的 —— 你明白我的意思吧,嗯?我会在“我该学习哪门编程语言”一章中详细讲述如何选择编程语言,所以在这里先不要有压力。
在这里我先快速提一下,选择哪一门编程语言可能没有如你想像中的那么重要。相反地,我会推荐你先选一门进行学习,而非试着去学所有世界上出现过的所有语言。
很多初学者甚至还没找到一份软件开发者的工作,就让自己尝试着去学习多门不同的语言。我觉得掌握多于一门的编程语言是必要的,但是我反对一开始就学习不同的语言,因为这样会很容易导致困惑,同时这会让你从其他真正需要学习的技术中分散精力。
我的建议是深入掌握一门编程语言,直到你有信心使用这门语言来编写任何的代码。
还记得我们在上一章讨论过的,在决定你想成为哪种类型的开发者时,目标要越明确越好吗?在选择编程语言时,也是一样的道理。
如何组织代码
在学习完第一门编程语言后 —— 或者在学习过程中 —— 下一件需要学习的事,就是如何合理地组织你的代码。
对于这项极有价值的技能,我在第一章的时候已经推荐过一个非常好的资料:Steven McConnell 的 《代码大全》。
我所说的组织代码是什么意思呢?
我指的是如何写出清晰易懂的代码,这些代码不需要大量的注释,因为它们都是自解释的。很多开发者终其职业生涯而没有掌握这一技能,这实在是相当不幸,因为我就是通过这一技能 —— 和其它的很多技术 —— 来评判一个开发者的技术能力的。
写出好的代码表明了一个人在仅仅把需求完成之外,还有他自己的追求。对代码进行组织确实是软件开发中属于艺术的一部分,但是这也是相当有难度的,因为你和你的同事都需要在你的代码上进行工作,并且会花很多时间在维护这份代码上,而非写新的代码。
我不会在本书中讨论关于如何写清晰的代码 —— 就像我说的 —— 我已经给你推荐过一份极好的资料了,但是你应该从一开始就学习如何写好的、清晰的代码,而不是等到后面才来学习它。
我可以保证,就算你是个初学者,但是只要你能写出优雅、整洁、干净、易懂并且能自解释的代码,在面试的时候,人家也会把你当成一个有经验的开发者。
这个技巧是必须掌握的,因为你将不仅仅把开发当成一份工作,而是将它将成自己的事业:这是工匠精神的体现。
面向对象设计
这一条是有争议的,特别是当你学习的不是一门面向对象(OO)的编程语言时,但是软件开发中主要还是以面向对象设计为主,所以你需要确保自己掌握它。
面向对象设计可以将复杂的程序设计分解为独立的类和对象(类的实例),这种方法可以对功能进行封装,并且每个类和对象都有特定的角色和功能。
在软件开发中,我们一直在做的就是管理复杂性。使用对象的方式进行思考可以帮助我们达到这一目的,因为它可以让我们用一堆相互关联的组件来定义和设计一个复杂的系统,而不用直接操作整个复杂的系统。
现在有很多的函数式编程语言了,但是你在软件开发过程中碰到的大多数语言和模式都还是严重地(如果不是全部的话)受到了面向对象设计与分析的影响。
你应该很好地掌握类、不同类型的继承 —— 包括何时使用它们 —— 以及类似多态和封装这些术语的含义。
算法和数据结构
如果你是在传统的大学或者学院学习计算机科学专业的话,算法和数据结构会在你将要(或者学过)的专业中占有很大的一部分。
算法是解决不同计算机科学/编程问题的通用解决方法。
举例来说,有很多算法可以用来对一系列连续的数据进行排序。这些算法中的每一种都有不同的特点,比如排序速度、内存大小要求、以及适合哪种类型的数据集。
在计算机科学中已经有很多这种现成的算法了,掌握如何写出这些现成算法的变体以解决在实际编程过程中碰到的困难问题也是相当重要的。
通常,一个算法厉害的开发者,可以在一个小时内解决其它程序员几天才能解决问题。除非你熟悉各种算法,并很好地掌握他们,否则你可能对一些现成的、优雅的解决方法全然不知。单从这个原因来讲,我就认为这是一门有价值的、值得学习的技术。
数据结构也是类似的,它算法相辅相成。
有一些数据结构是所有软件开发者都必须掌握的:
- 数据和向量(vector)
- 链表
- 栈
- 队列
- 树
- 散列表
- 集合
对数据结构和算法的掌握,可以帮助我们轻松并且优雅地解决很多困难的编程问题。
在我刚开始编程的时候,我的数据结构和算法都非常烂,因为我基本上是自学出身的。
直到我在一个叫 TopCoder 的网站上进行竞赛的时候我才真正认识到它们的价值,掌握数据结构和算法并熟练地操作它们,可以给你带来很大的竞争优势。
很快我就明显地感觉到这些技术在真实的编程世界中有很大的用处,因为一些我之前无法解决的问题,现在可以很轻松 —— 并且很有趣 —— 地解决了。
事实上,我觉得这是所有软件开发所有领域中最有趣的部分之一。当你使用数据结构和算法对一个困难的编程问题提出简洁、优雅的解决方案时,你的成就感会爆棚的。
最好的资料(至少在本书写作时)是 Gayle Laakmann McDowell 的一本极好的书 《Cracking the Coding Interview》(中文版:《程序员面试金典》)。
在这本书中,她讲解了所有你需要掌握的算法和数据结构。
学习数据结构和算法很费劲,但是完全值得,这是一项可以让你在同事中脱颖而出的技能。大多数软件开发者在这方面知识都少得可怜。
同时,如果你想通过类似微软或者 Google 这种大公司的面试,这项技能也必不可少。
开发平台及其相关技术
你应该熟练掌握至少一种开发平台及其相关的技术,或者与这个平台有关的框架。
我所指的平台是什么意思?
唔,通常来说,它代表的是操作系统,不过它也可以应用于某种类似操作系统的抽象上。
举个例子,你可能是使用 Mac 或 Windows 进行开发的 Mac 或 Windows 开发者,同时你也可能是个专注于某个 web 开发平台的 web 开发者。
我不想针对开发平台的确切意思展开讨论 —— 不同的人会有不同的意见 —— 但是针对这里要讨论的,我将开发平台定义为一个你用来进行开发工作的具体环境,它有自己的生态系统和特殊性。
再次地,我想说选择哪种开发平台并不重要,重新的是你要选择一个。
公司通常会聘用使用特定平台或技术进行开发的开发者。
假如你是一个 iOS 开发者,你要是可以熟练地在这个特定的平台上进行开发,你就会更容易地获得一份工作。
掌握开发平台不仅需要对平台本身的熟悉,同时也要熟练使用该平台相关的开发工具,通用模式及常用的框架。
你可能会觉得编程语言的选择限定了你对平台的选择,但是通常情况下并不是这样的。
以 C# 来举例。你可以使用 C# 来为 Windows,Mac,iOS,Android,Linux 甚至是嵌入式系统进行开发。
所以,在你选择编程语言的同时,也要选择一个开发平台。
框架和技术栈
除了学习一门具体的编程语言和开发平台工具,我也强烈推荐你学习某种框架,当然更好的是掌握与这种框架相关的技术栈。
什么是框架?
什么是技术栈?
简单来说,框架就是帮助我们在某个平台,或者跨平台进行开发的类库集合。通常情况下,它可以使我们更加简单地完成该平台上的常见编程任务。
回到 C# 的例子中来,大多数的 C# 开发者使用 .NET 框架进行 C# 应用的开发。.NET 框架由很多类库和类组成,它们可以让开发者在更高级的抽象上进行开发,避免每次完成某些任务的时候都需要重新发明轮子。
举例来说,.NET 框架中包含了操作图片功能的代码。想要从零开始去写这些代码是很困难的,所以对于想进行某种图片操作的 C# 开发者来说,使用框架就有了巨大的好处。
技术栈稍有不同。技术栈是指我们开发某个完整应用时,经常会一起使用的一系列技术,通常包括框架。
举例来说,有一种常用的技术栈称为 MEAN 栈。这代表了 MongoDB,Express.js,AngularJS 和 Node.js.
MongoDB 是数据库技术。
Express.js 是用于开发 web 应用程序的 Node.js 框架。
AngularJS 是一个前端 JavaScript 框架,用于开发 web 应用程序的用户界面。
最好,Node.js 是一个使用 JavaScript 来开发 web 应用程序的运行时环境。
你并不需要完全理解这些词的意思 —— 除非你就是想成为一个 MEAN 开发者 —— 更重要的是你要明白,如果你掌握了所有的这些技术和框架,你就可以开发出一个完整的 web 应用。
技术栈让开发应用变得更简单,因为它们为你提供了大多数开发者用于开发应用的通用范式,所以这些知识可以很容易地进行分享,你确定这一系列的技术可以很好地一起工作,因为这已经被其它开发者证明过了。
学习某种技术栈相当有价值,因为这代表你拥有了开发一个完整应用所需的全部技术。很多公司都有使用某种技术栈开发的应用,这种公司更愿意寻找熟悉使用这种技术栈的开发者,因为这样他们就能更快地上手进行开发了。
基础的数据库知识
数据库的整体景观在过去几年中发生了很大的变化,但是我没有看到它们会很快消失的迹象,因此我觉得你至少应该掌握一点数据库的基础知识,你觉得呢?
在写作本书的时候,有两种主流的数据库技术:关联型数据库及文档型数据库。我认为一个开发者至少应该熟悉关系型数据库,然后对文档型数据库有一些了解。
在软件开发中,数据库经常被用于为应用存储数据。
有一些团队会有专门的数据库开发人员或者数据库管理人员(DBA),但这并不能成为你不去学习一些数据库基础知识的理由。
最低的限度,你应该掌握如下内容:
- 数据库是如何工作的
- 如何进行基础的数据查询
- 如何插入,更新以及删除数据
- 如何对数据表进行连接
除此之外,你可能还需要知道如何在你的开发平台及框架中使用代码对数据进行查询和存储。大多数的开发者都应该可以使用代码与数据库进行交互。
源码控制
源码控制也是软件开发项目中必不可缺的一部分。
在没有源码控制的年代,我们只能通过网络共享所有的项目文件,或者通过 U 盘来分享不同版本的项目。
我必须很羞愧地承认,在我的开发生涯中,我不止一次使用这种方法管理项目。但是,那时我还太年轻,太傻。你大可不必也走这样的弯路。
今天的所有专业程序员都至少应该掌握如何使用源码控制对代码进行签入,签出以及对代码的变动进行合并。
在最基础的层次上,源码控制就是用来帮助你保存一个软件项目中不同文件的改动历史的。它同时也允许多个开发者同时对一个项目进行开发,并将他们做的改动进行合并。
我不会在这里深入讲解细节,但是你至少应该很好地掌握一个源码管理系统的使用,同时你应该对大多数源码控制的基础概念了然于胸。
在今天的软件开发世界上,几乎所有的专业开发团队都会使用某种的源码控制。
构建与部署
大多数的的软件项目都有某种的自动化构建及部署系统。
现在已经有很多不同的软件可以帮助团队对这些在过去需要手动完成的工作进行自动化,但是有一些团队还是依然使用手动方法。
你问我什么是构建和部署?
好问题。你现在应该知道如何将你所写的代码签入到源码控制系统中吧?
通常情况下,在代码签入到源码控制系统中时通过某种方式确保它们能正确运行,通常是一个好主意。
而这就是构建系统存在的意义。在最低的限度上,构建系统可以对所有代码进行编译,确保当中没有存在编译错误。而一个完善的构建系统同时会运行单元测试及用户测试,运行代码质量检查,还会为代码库提供某些当前状态的报告。
部署系统则是负责将代码部署到生产机器上,或者可能是某些类型的测试环境上。
你不需要是这些技术的专家,但是掌握一些基础知识也是相当重要的,包括这些系统如何工作,构建及部署代码的流程。
通常,真正负责创建和维护构建部署系统的是一个最近正在快速崛起的领域,被称为 DevOps (developer operations 的简称)。
同样地,这并不能成为你不去了解这些流程是如何工作的理由。
测试
在过去,做为一个程序员是不需要懂得测试的。
在过去,我们只需要写完一堆代码,将它们丢给一堆测试,测试就会将代码中的一堆 bug 找出来,我们对这些 bug 进行修复就行了。
现在已经不是这样的时代了。
现在很多的软件项目采用的是敏捷开发(我们会在开发模式中详细进行讨论),这要求程序员和测试之间有更紧密的合作。
保证软件质量现在已经成为整个小组的责任了 —— 其实我认为一直都是这样。
因为,你也需要懂得一点测试的知识。你至少应该熟悉如下的这些术语:
- 白盒测试
- 黑盒测试
- 单元测试(不是真正的测试)
- 边界条件
- 测试自动化
- 测试验收
一个好的开发者 —— 同时我假设你至少想成为一个好的开发者 —— 在将代码交付给别人之前,都会先对自己的代码进行测试。
如果你想成为一个专业的程序员,而不仅仅是一个黑客,这一点是不容商榷的。
调试
很多软件开发新手的梦想都被调试器毁了。
每个人都想写代码,不是吗?有人希望自己一直在调试代码吗?
欢迎来到真实的世界。
你作为一个软件开发者的 90% 时间都会花在搞明白为什么你的代码不能正常工作。
我知道这个事实并不令人向往。我知道你很想把整天的时间都拿来写新的代码,但是这个世界并不是按照你的心意运转的。
如果你使用了测试驱动开发,你可能会少花很多时间在调试器上,尽管如此,无论你做什么,不管你如何努力去避免它,你还是得学习如何调试自己或者他人的代码。
所以,以其让你对自己不得不做的事情一知半解,还不如痛下决心去真正掌握如何高效率地完成它。
在关于调试的章节,我会更详细地讨论这部分内容,而现在,你需要知道如何去做。
软件开发方法
被这一长串你所需要掌握的技能清单吓到了吗?
如果还没有的话,这里还有一条 —— 但是我保证这是最后一条了。
一些开发团队只是简单的从写代码开发,直到把所有的事实都做完,而大多数团队都会使用某种类型的开发方法,或者至少假装他们在使用。
(顺道说一句,不要期望任何团队会真正做到他们声称在使用的软件开发方法。我并不是想批评谁,或者要对谁指手画脚。我只是一个实用主义者,同时我碰巧知道很多人声称他们在使用某种软件开发方法,比如说敏捷开发,只是因为他们每天都会开一个立会。)
因此,你至少应该对大多数常用软件开发方法的基础知识有一个了解。在目前,常用的方法就是瀑布式开发和敏捷开发。
很多团队都声明他们自己使用敏捷开发。敏捷本身的定义很宽泛,但是它包含了很多实践,或者说仪式在里面,你必须要明白这些才能在一个敏捷团队里面生存。
我们会在软件开发方法一章中深入讨论这个技术。
信息量太大了吗?不要慌
我知道这些知识很多,而我们都还没真正触及到大部分的主题的表面。
现在你可能会觉得信息量有点过大,觉得自己对这些技术的大部分都不懂。在目前这个阶段,什么都不懂是正常的 —— 除非你已经是个有经验的软件开发者了。
不管怎样,我会在“软件开发所要掌握的技能”一节中对大部分的技术进行更深入的讲解。所以,你现在只管放轻松,不要怕。
接下来,我会教你学习技术的通用方法,这样在后面的章节中碰到这些具体的技术时,你就会知道如何正确地学习它们了。
Hey John
我注意到在书中有很多的链接,看起来你好像在推广一大堆你的其它产品跟作品...这到底是怎么回事呢?
唔,我很高兴你问到了这个问题。
首先,让我们来谈谈这些链接。
是的,这本书里有大量的链接。但是,不用担心,你不需要打开全部的这些链接。你完全可以随意点开,或者只看那些你感兴趣的。
大多情况下,我都尽可能将我之前写过的与该主题相关的信息附到链接上,因为有人可能会对某个主题感兴趣,并想深入进行了解。
这些链接大多数会指向我的博客或者 YouTube 视频,通常我会在那里讲更多关于这个主题的事情 —— 或者仅仅是因为好玩。
(同时,如果你点了这本书上的任意一个链接 —— 或者将它们手动敲入你的浏览器中 —— 你会被带到一个页面,这个页面分章节地列出了这本书中的所有链接)
至于插入我其它产品这件事,是的,你是对的,我确实正在做这件事。
我觉得这是很明智的。
书本身是很便宜的,写一本书并不能赚很多的钱。
事实上,如果你写一本书,你应该拥有写这本书的其它理由,而不仅仅是因为写书能赚钱。而我写这本书的一个原因就是为了帮助推广其它我觉得对你也有价值的产品及“作品”。
这并不意味着我在给你发垃圾信息,你完全可以不买任何东西 —— 这本将近 800 页的书本身就已经具有它很大的价值了 —— 但是,如果你有兴趣的话,这些产品就在那里,同时我也会继续推广它们。