Introduction?引 言各位读者,大家好!或许你现在还是一名在校大学生,立志在毕业之后找一份程序员的工作,开始自己的职业生涯;或许你已经在一家公司“搬砖”,过着稳定的打工生活;或许你是一名创业者,时不时还要写点代码;或许,你只是对.NET平台和C#语言软件开发有浓厚的兴趣。总之,你一定是对自己现在掌握的C#知识还不满意,希望更上一层楼。如果是这样的话,本书就是为你而写的。本书不适合完全不了解C#的人士阅读,所以我假定你至少有一点C#的开发经验,懂得C#的基本语法。
那么一个合格的.NET程序开发人员,需要掌握哪些知识?这些知识应该如何去准备?如果把.NET程序开发人员简单地分为初级、中级和高级的话,自己又应当属于哪一级呢?下面先从.NET程序开发职位要求讲起。
.NET程序开发职位要求曾几何时,面向对象编程语言是Java一统天下,但现在,.NET开发的职位越来越多,很多大型企业也选择.NET平台搭建自己的系统与服务,在各大招聘网站上都活跃着大量的.NET开发职位,这些职位的技能要求互不相同,但可以简略归纳为三部分:
必要技能:包括主语言相关、设计与架构相关、岗位相关、数据库相关、线程相关以及语言相关。
加分技能:包括软件工程相关以及其他。
软性技能:包括文档书写、分析问题与解决问题的能力、沟通能力等。
例如,图1为某招聘网站上的一个“.NET资深开发工程师”的岗位要求。其中第1~5条都属于必要技能,包括对.NET平台开发经验的年限要求,以及掌握ASP.NET. MVC、WebAPI等各类.NET平台部件的要求。第4条为设计与架构相关要求,第5条则是数据库方面的要求。第6~7条为软性技能,第8~9条为加分技能(通常有“优先”等字)。
那么,知道了应聘的要求,我们该如何进行准备呢?针对每种不同要求,又需要如何学习?下面主要讨论必要技能和加分技能。
必要技能虽然各个岗位对必要技能的要求不同,但一般来说,必要技能可以划分为几部分,如图2所示。本书重点讨论C#相关和线程这两部分,对设计与架构涉及较少。岗位相关、数据库和语言技能则不在本书的讨论范围之内。
C#相关由于本书主要讨论.NET和C#,所以我就默认C#是岗位要求的主语言。对于.NET程序开发人员来说,主语言包括C#本身,以及它的运行环境.NET开发平台。对于C#语言来说,我认为十分重要,必须要掌握的知识点如下(参见图3):
.NET平台基础知识,包括.NET平台构成,.NET平台语言的编译(IL和JIT),以及编译之后的结果—程序集的结构和部署。另外,什么时候需要直接操作程序集(反射),及其优缺点。
C#类型基础。C#包括引用类型和值类型,及其区别和联系,它们在内存上又是如何分配的。
C#作为面向对象的语言,是怎样体现了面向对象的三大特征:封装、继承和多态的,接口、抽象类的区别和联系,以及何时考虑使用接口。
内存管理和垃圾回收机制是什么样的;根据CLR的垃圾回收机制,我们又应当做些什么。
C#中主要的数据结构的区别和联系。C#提供了非泛型和泛型的集合,在什么情况下,选用什么数据结构,Array、ArrayList和List的区别和联系,字典的实现原理,不同数据结构查找和插入/删除的时间复杂度等。
C#每一代的主要特性:1)委托与事件、反射;2)泛型;3)LINQ;4)动态语言运行时;5)async/await归到异步部分(暂时不在这里提及)。其中,又以LINQ尤为复杂,它包括了扩展类型、Lambda表达式(表达式又是一个很大的话题)、闭包等,这些都是面试时常见的问题。对于这些形形色色的特性,除了可以答出它们的定义之外,还需要知道,为什么要引入它们,引入它们是为了解决什么问题,在没有它们的时候,同样的问题又是怎样解决的。
图3 .NET程序开发必要技能地图—C#相关对于上面这些问题,本书会一一进行讨论。上面这些知识点的掌握,是在简历上写下“熟悉C#”(注意,这里我没有使用“精通”二字)的前提。这部分知识也是面试时的重中之重,面试官筛人的利器。如果这些知识都不是很清楚,那么“熟悉C#”也就成了一句笑话。
设计与架构相关设计与架构相关的内容如图4所示,其重要性仅次于主语言,因为这个技能严重影响代码质量。这块内容的学习和理解绝非一日之功,对它进行“临时抱佛脚”基本是不可能的,通过考察面试者对设计模式、面向对象的理解,基本可以准确地将面试者归到高手、中等和初学者这三类中。当然,如果岗位本身比较初级,那么这方面的要求将会相应降低。
因为C#是一个面向对象的编程语言,所以,面向对象成为面试考察的重点内容。经典的设计模式就是灵活运用面向对象的结果。常用的知识点包括:
面向对象设计五大原则。光背书没用,一定要用过(在项目中用或者自己用)才能有自己的心得体会。
常用设计模式,包括单例模式、策略模式、观察者模式、工厂方法模式等,及其UML类图。
依赖注入的概念,以及依赖注入的工具。
对所有设计模式的全面讨论超出了本书的范围。本书第4章“C#和面向对象”会简单介绍面向对象设计五大原则。另外,本书会在讲述C#语言特性时穿插一些常用设计模式,例如事件和观察者模式、开闭原则和工厂方法模式等。
对设计模式的学习,可以参考著名的《设计模式:可复用面向对象软件的基础》这本书,它是设计模式的开山之作。另外,程杰的《大话设计模式》这本书,也以生动有趣的方式讲述了各种设计模式的原理和用法。然而,最重要的还是自己亲自操作实践,以写代码的方式体会设计模式的好处。
岗位相关如果用人单位招的是ASP.NET程序员,那么肯定得了解ASP.NET生命周期、路由、前后端传值、MVC,以及至少一门前端语言等。如果招的是后端,可能会问一些关于Web服务、WebAPI的知识。专门负责写WPF应用的岗位,可能会在线程上大做文章。这些知识都是.NET框架类库的一部分。本书不会讨论具体某个框架类库的使用,.NET平台各大主流框架类库都有众多相关书籍供参考。
当然,框架类库的基础知识点也很重要。例如对WPF,如果你不知道如何禁止用户更改窗口的大小,那没什么关系,上网一查即可;但如果你不清楚长任务时如何保证界面良好的响应,工作线程如何更改UI线程控件的值,那么你编写出来的WPF应用一定会让用户怨声载道。
有些岗位还需要应聘者清楚分布式、脚本语言、Linux环境、缓存、消息队列、高级算法、大数据应用等相关知识。对这些知识的掌握和理解,一方面需要看书,另一方面也要结合相关项目经验。岗位相关的知识点五花八门,因岗而异。
数据库相关确实有一些开发者不需要和数据库打交道,不过,大部分岗位都要求对数据库操作有一定了解。数据库方面的技能如图5所示,如果一个岗位要求熟悉数据库,那么面试官期待的将是:
使用主语言访问数据库并熟练掌握增删改查操作。对于C#做主语言的情况,可以使用非ORM(ADO.NET)或ORM(Entity Framework)两种工具。你了解你目前所使用的ORM吗?基本的SQL书写。DBMS常用对象及工具,例如表、视图、存储过程等。
数据库基础知识,例如什么是范式,为什么数据库要遵循范式,不遵循范式的数据库会产生什么问题,什么是索引(聚集索引和非聚集索引),索引的利弊等。
什么是事务,为什么需要事务,没有事务会怎么样,解释事务隔离层级。
上面说的都是关系型数据库中最重要的知识点,有些岗位还需要应聘者懂得非关系型数据库、数据仓库等。而至于数据库的一些其他知识,例如存储过程、触发器、性能优化等,限于篇幅,这里就不详细展开了,应聘者可以根据岗位需求自行准备。《数据库系统概念》是一本非常经典的大学教材及优秀参考书。
线程相关很多复杂的应用都会出现多线程的身影,线程相关的技能如图6所示。Windows操作系统赋予了我们使用线程的能力,我们可以利用多线程改善程序的性能。对这一块知识,很多初级开发者都不清楚,可能是由于没有机会写一个需要多线程的应用。关于多线程的材料较少,而且多为英文,也是初级开发者对于线程不清楚的另一个原因。
图6 .NET程序开发必要技能地图—线程相关但是,大型应用,或者对性能要求很高的应用,多线程则无处不在。.NET本身也提供了非常丰富的线程管理类库。本书第17~21章试图对这一块内容进行较为全面的讲解。
语言相关这里的语言相关是指使用英语的能力。具体来说,包括阅读英文文档、英文邮件写作,甚至使用英语和他人进行沟通的能力。对于外企来说,这块非常重要,而非外企则相对不那么重要,但由于目前大部分较为权威的文档和资料仍然是英文的,而且缺乏翻译,所以开发者还是需要把自己的英语水平提升,能够无障碍地阅读英文技术文档。
这一块的学习只能通过日积月累,别无捷径。不过,我不推荐大家马上拿来一本四六级甚至托福单词去背,因为,其中大部分单词在实际开发中都遇不到,而真正需要知道的单词(例如,delegate委托,interface接口等),要么不在词汇表里,要么根本不是这个意思,而你把abandon(四级的第一个单词)背得再熟,平时也基本看不见它。更快捷的方法是阅读MSDN文档,并把不会的单词记录下来。
加分技能软件工程和项目经验相关虽然也有单枪匹马搞定项目的例子,但那通常出现在“远古时代”,现在的软件开发项目越来越复杂,常常需要多个人组成团队一起合作。团队会有专门的项目经理负责需求的整理(也可能没有,如开发者自己兼职项目经理),制定开发进度,开发者同心协力,从小目标开始,分而治之,最终完成项目。面试官(可能是开发者,可能是管理开发者的团队领导),不仅仅关心一个团队新人是否有能力完成领导交给他的任务,也会关心这个新人是否可以和现有人员通力合作。面试官可能会问以下问题,并根据你的回答默默思考你和新团队的契合程度:
项目经验。你之前做过什么,最得意的项目是什么,你在其中处于什么角色,解决了什么问题。
你之前的项目是瀑布开发模型还是敏捷,你更喜欢哪种,敏捷有什么优点和缺点。
你之前公司的代码是如何实现版本控制的。
你对单元测试有什么认识,是否写过单元测试代码。
如果面试者对这一块很不清楚,或者,面试者之前完全没有用过相关的工具(代码控制、测试等),面试官可能会担心