引言
各位读者,大家好!或许你现在还是一名在校大学生,立志在毕业之后找一份程序员的工作,开始自己的职业生涯;或许你已经在一家公司“搬砖”,过着稳定的打工生活;或许你是一名创业者,时不时还要写点代码;或许,你只是对.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文档,并把不会的单词记录下来。
加分技能
软件工程和项目经验相关
虽然也有单枪匹马搞定项目的例子,但那通常出现在“远古时代”,现在的软件开发项目越来越复杂,常常需要多个人组成团队一起合作。团队会有专门的项目经理负责需求的整理(也可能没有,如开发者自己兼职项目经理),制定开发进度,开发者同心协力,从小目标开始,分而治之,最终完成项目。面试官(可能是开发者,可能是管理开发者的团队领导),不仅仅关心一个团队新人是否有能力完成领导交给他的任务,也会关心这个新人是否可以和现有人员通力合作。面试官可能会问以下问题,并根据你的回答默默思考你和新团队的契合程度:
项目经验。你之前做过什么,最得意的项目是什么,你在其中处于什么角色,解决了什么问题。
你之前的项目是瀑布开发模型还是敏捷,你更喜欢哪种,敏捷有什么优点和缺点。
你之前公司的代码是如何实现版本控制的。
你对单元测试有什么认识,是否写过单元测试代码。
如果面试者对这一块很不清楚,或者,面试者之前完全没有用过相关的工具(代码控制、测试等),面试官可能会担心这位面试者写出来的代码质量不高。不过,如果岗位没有对这一块具体写出要求,那么这部分是锦上添花,会的话加分,不会也“罪不至死”。
其他个人经历
这部分主要包括个人网站、社区贡献(如写书、翻译、MVP、论坛回答问题等)、开源项目,甚至个人出版物等。随着网络的开放,开源运动的兴起,越来越多的开发者愿意分享自己的知识和代码到社区,也对其他开发者的批评和指正报以积极的回应。
由于大部分人都没有什么社区贡献,因此,在社区积极热心提供知识的那些开发者就很容易脱颖而出。参与社区的活动会扩大自己的人脉,从而对找工作有着积极的作用。而且,对社区的贡献也体现出一个人在工作之余,仍然对技术有着浓厚的兴趣,并愿意将自己的心得体会分享给他人。
高级技能
除了上面列出的技能外,如果应聘的职级较高,那么还可能会有属于高级开发人员的一些必备技术型技能。这些技能不是一项特定的技术,而是各项技能的综合,用于解决一些特定的问题。
例如,大部分大型IT公司都拥有一个自己的门户网站,它的访问量是十分巨大的,因此,大型IT公司的高级开发人员必须熟悉如何让系统在超高并发下保持稳定,找出系统性能的瓶颈,然后对其进行优化。对这个问题的解答,并不限于一门语言或一种工具,而涉及方方面面的知识,这些知识的积累通常需要完整经历一个大型项目,并且该项目要足够大,这就限定了先决条件—小公司基本上是无缘大型项目的。具备高级技能的开发者在就业市场上屈指可数。
.NET程序开发进阶之路
在下面的讨论中,我简单地将.NET程序员分为初学者、中级和高级开发人员三类。
初学者
刚工作几年,也许用C# + ASP.NET写过一个订单管理系统,该系统可能包括若干页面、一堆表格,本质是数据库CRUD。这个系统东西虽小,但五脏俱全。有些开发者的系统写出来是这样的:
没有合适的架构,控制器有时直接获取数据,有时又通过其他函数获取。
没有任何测试保护。
前端后端代码一团糟,毫无代码质量意识,例如,长达数百行的函数、超多层if嵌套、命名诡异等。
不留注释。
懒人异常处理法:catch(Exception ex){/*…*/}。
类似的问题还有很多,而写出这种系统的开发者无疑属于初学者(即使他做了很多项目)。初学者还有一个典型的特性,就是完全看不懂技术专家在写什么。例如,技术专家写了一篇优化反射性能的文章,初学者却连什么是反射、委托、IL都不知道。
当初学者去了几间比较大型的公司应聘之后,发现他的订单管理系统并未受到面试官的青睐,而面试官提出的问题大部分都是“C#相关”中的知识点,而他一问三不知。受到若干次挫折之后,有些初学者选择开始从头看书,好好学习,有些初学者则抱怨大公司总是“考背书”。
计算机领域中,开发者人才济济,逆水行舟,不进则退。如果初学者永远不进步,迟早会被公司和社会淘汰,会有新人来顶替你。因此,很多初学者都选择在工作之余读书进修,攻克自己还不清楚的技术知识点。
中级开发人员
如果你已经清楚了“C#相关”中的绝大部分知识(当然面试官还是很有可能问倒你的),对答如流,并且熟悉基本的设计与架构知识,你就可以算是中级开发人员了。中级开发人员的ASP.NET订单管理系统就比初级人员写出来的强多了,例如:
前后端代码质量脱胎换骨,通常都可以通过所谓的“醉酒测试”(即给一个喝醉了的开发者来看,他也能看得懂)。
有明确清晰的架构,每层只做每层该做的事。
基本符合SOLID。
如果使用ORM更合适,会使用一款ORM。
努力优化自己的代码。
努力进行单元测试和集成测试。
在异常处理和日志记录上下了很多工夫。
一个称职的ASP.NET方向的中级开发人员应该可以独立完成该系统,或者指导若干初学者通力完成。不过,当该系统规模越来越大,访问量越来越多时,中级开发人员现有的知识储备已经不足以保持系统的稳定运行了。例如,需要引入数据库的读写分离、服务器的负载均衡等,这些都超出了.NET和C#的范围,而需要学习更多知识。此时,他们就会求助于高级开发人员。
高级开发人员
高级开发人员需要掌握的知识早已超出了本书的范围。高级开发人员不仅熟悉本书提到的大部分知识,另外在性能优化等其他专题上有自己的心得。他们可独自冲锋陷阵,解决初级和中级开发者解决不了的问题,还可以指挥开发团队通力合作,完成大型项目。系统性能变差但不知道原因,出现bug解决不了的时候,大家一筹莫展,齐刷刷地把头望向高手:怎么办?名副其实的高级开发人员,通常都可以完美地解决问题。
本书的结构
本书分为三部分:
基础知识(第1~7章):包括.NET的相关知识、C#的类型基础和内存分配、继承和多态、字符串相关知识、垃圾收集、异常处理等。
C#特性(第8~16章):从委托事件开始逐一介绍C#各版本的主要特性。
多线程和异步(第17~21章):介绍多线程的基本概念、线程同步工具以及不同C#版本的异步编程模型。
本书参考的主要资料
下面这部分内容是本书主要的参考资料简介,有的偏理论,有的偏实用。
《CLR via C#第4版》Jeffrey Richter
这本书实在太重要了,太有名了。实际上,它几乎出现在任何一本C#书籍的参考资料中。该书虽然现在看来已经有点“过时”了,但它对CLR的讲解十分透彻,仍有价值。很多国内作者写的C#书籍,都或多或少地受了这本书的影响。
该书虽然很厚,但结构十分清晰,分为五大部分:
CLR基础,讲程序集的结构和部署、IL、JIT、类型系统。第1章很重要,必须好好看。
设计类型,该部分遍览了一个类型可以拥有的所有成员,所有章节都很重要,第12章“泛型”尤其重要。
基本类型,第13、14、16、17、19章很重要。
核心机制,主要包括异常处理、GC、应用程序域、反射和序列化。
线程处理,作为Windows操作系统的大师,作者对线程的理解非常深入。第26章主要是概念,第27~30章全是多线程,通读、阅读这部分对多线程的理解帮助极大。
这本书由于成书较早,因此缺失了对C#一些较新版本功能的介绍,例如LINQ等。
《深入理解C#》Jon Skeet
这本书相比上一本不那么“底层”,不过,它的阅读难度也不小。对于更喜欢特性而非原理的读者,可以通读一遍此书,它按照演进顺序讲述了C# 1~5的所有特性,对LINQ、异步的讲解既实用又涉及原理。这本书所有章节都很重要。
《.NET设计规范:约定、惯用法与模式》Krzysztof Cwalina
在争论应该是抽象类还是接口,应该是类还是结构时,我们其实看看这本书就够了,它早就给了我们一大堆最佳实践。不知道怎么书写异常处理?看看该书的第7章吧。这本书实际上就是一个代码规范集合。
这本书适合在需要的时候随时查阅。以上三本书相辅相成,包括了一个中级开发者需要掌握的所有语言相关技能。实际上,即使只理解一半也已经足够好了。
《Pro .NET Performance》Sasha Goldsftein
这本书以一个独特的视角—性能作为切入点,讲述了.NET程序和类型在性能这方面的体现。该书的前两章主要讨论了性能测试的衡量方法和工具,第3章深入介绍类型系统,第4章详细讲述了GC,这两章值得细读。这本书目前只有英文版,阅读难度很大。
《.NET本质论(第一卷):公共语言运行时》Don Box
这本书实际上就是在讲CLR,也是据我所知对CLR的探讨最底层、最深入的一本。该书的作者同时也是COM专家,因此,对于CLR这个更好的COM来说,他必然驾轻就熟。我最喜欢这本书的第6章,作者使用了一章的篇幅讨论了方法调用。该书过于底层,成书年代也很早,读起来可能有些脱离实际的感觉。
《NET 4.0面向对象编程漫谈:基础篇》金旭亮
金旭亮老师的这本书(以及下一本书)以生动有趣的笔触讲解了.NET的方方面面。我个人非常喜欢这本书。如果你觉得《CLR via C#》太枯燥,行文方式又过于“老外”,看不下去,可以先看这本。这本书虽然没有《CLR via C#》那么深,但对于底层也有颇多涉及,它和很多粗制滥造的“拖控件教程”有着本质的不同。
《NET 4.0面向对象编程漫谈应用篇》金旭亮
作者在该书中着重分析了进程和线程以及在C#中的实际应用,这是多线程方面为数不多的好资料。
《你必须知道的.NET(第2版)》王涛
这本书的编排顺序十分独特,它的视角是完全面向对象的,并且将.NET各个知识点以逐个对比的方式呈现在读者面前。第一次阅读时,可能会觉得不太适应。这本书有一定深度,而且作者行文比较幽默,因此读起来也不是很枯燥。这本书有很多SOLID和设计模式方面的内容,对开发者不无裨益。
《Threading in C#》
这本书(以网页形式在网上公开)提供了另外学习C#多线程的资料,目前已经有翻译版本https://blog.gkarch.com/threading/part1.html。该书对.NET提供的各种各样的锁都有所涉及,可以和《CLR via C#》最后四章一起看。
本书的开发环境
本书使用Visual Studio 2017 Community + Windows 7进行开发。Visual Studio 2017 Community是完全免费的,你可以在https://www.visualstudio.com/downloads/下载它。
代码下载与联系作者
本书的代码可以从下面的链接获得:https://github.com/s055523/CodeForCSharpBook。
由于笔者水平有限,书中或代码中难免会出现一些错误。如果你在阅读时发现了任何问题,请务必反馈给我。可以通过我的博客地址:http://www.cnblogs.com/haoyifei/或邮箱s055523@gmail.com联系我。
致谢
首先要感谢我的妻子王妍在我写书时的全力支持和理解。没有她在背后的付出,这本书是不可能很顺利完成的。
我还要感谢李志,王清培、凌光、张子阳,他们为本书的写作提出了很多宝贵的建议,并撰写了推荐语。最后,感谢机械工业出版社责任编辑吴怡女士,她丰富的出版经验与认真的工作态度,是这本书得以出版的前提。