01
近年来,有些读者会问我一些形形色色的问题,让我很难去回答,甚至给不出建设性的意见。
举个例子:
- 我学习什么能进入优秀的互联网公司工作?
- 我想做研发我应该学习什么?
众所周知,这问题就像你问学霸说你这么厉害一样让人难以回答。我作为一个双非软工本科学生,经过大学自己摸索和不断试错,毕业开始在百度从事研发工作。其实,我当时也有很多的疑惑,在这里给大家讲讲我的踩坑历程。
记忆中,我当年逛知乎、求助高人、甚至我的导师,都无法给出一个可操作的建议。除此之外,在我那种二本学校,知名企业都不会去咱学校校招,我和学长们对春秋招的概念微乎其微,进大厂是件很困难的事情,概率与踩狗屎不相上下。
作为探路者,求助知乎和论坛,给出的结论几乎都是好好学习数据结构/算法、现在大数据很火你应该学学Hadoop/Spark、你要是会微服务、docker、k8s一定会很加分。
让我想起了我当年问学霸题目如何解?学霸说:这个题目是来源于第X章第X例题,你这样解,答案就出来了,很容易的。至于为什么他能想到,鬼也不知道。
当时,我真的是花里胡哨的啥都学,啥都去倒腾,不知道是不是梁静茹给我的勇气。前端、后端技术栈、Hadoop/Spark、docker/k8s这些几乎都实操过,只是很多只是入门并没有深入研究,效果自然也十分有限。
这些概念,对于小白或者在校生来说,这仿佛在对说你不用学了,除非你天生技术欲望特别强烈。这对于大多数普通人来说,明显是劝退的节奏,可操行十分有限,几乎没有参考价值,不知道从何下手。
其实,道理是没有错的,多研究底层和热门技术栈是有益的。但是,脱离实际情况谈技术就是扯犊子,就像让中国男足拿世界杯冠军显然不符合实际,更应该是根据实际情况,做产出最大的事情,否则会信心全无。
接下来,我系统性拆分问题,在不同阶段应该「学什么」、「如何学」、「学到什么程度」,重点讲我当时遇到的问题,还有我是如何去思考的,最终如何解决的,思路比结论重要。
02
根据问题归类来看,主要在我自己的角度谈谈普通本科如何实现进入Top级互联网工作?
首先,说说在大厂工作都是些什么样的人,他们当年都是背着什么光环混进去的?
经过我的调研和分析,重点说一下在校招中面试官看中和考察的东西。
- 学历/专业、扎实专业基本功
- 有成果的科研经历
- 省/国家级软件设计大赛
- 丰富互联网公司实习经历
- 小有名气的开源项目经历
大概思路就是,要么你证明你令人信服的天赋如逻辑系统思维、聪明,让人觉得你可以被快速培养;要么你有丰富的工程实战经验,证明你具备优秀工程师的潜质。
当然,你可能会说这么多要求,恐怕神仙也做不到啊,简单太苛刻了。在这里,并不是上述要点全部满足,只是满足其中两项证明你的实力即可,毕竟面试时间十分有限必须有点让人信服的东西啊。
举个例子:
1、假设你是上海交大、华中科大大学毕业的学生,你可能只需要重点复习数据结构/算法等专业知识,辅之把学校的科研经历说一下。可能进入什么阿里华为百度问题都不是很大,专业知识对于你们来说自己不再话下,毕竟考理论就是你们的特长。
2、假如你是双非大学毕业的学生,那么你必须用国家级大赛、开源项目、互联网公司经历证明自己。总之,多做项目,专注于技术本身,让自己更早具备职业软件工程师的实战技能。
简而言之,你没有光环,那就比别人多努力点,提前做好职业规划,把时间投入技术本身不要投机取巧。
03
鉴于上述分析,知道需求是什么?对于我们来说,主要把精力投入在技术本身。
接下来,我们将面临一系列问题。
- 我应该做什么方向?(方向)
- 我应该学习什么内容?(规划)
- 我如何学这些内容?(方法/策略)
- 我应该学到什么程度?(量化)
- 如何把理论用到实际项目/产品中?(产出)
不同方向,意味着不同领域不同,学习的知识和实战项目有共性也有差异。在这里,我主要讲一下通用的思路。重点拿我擅长方向举例,其他方向可按照同样思路举一反三。
根据我的经验,可将内容分为原理、应用、擅长方向三个纬度。原理和应用纬度必须学习,方向纬度根据自己擅长方向深入学习。
原理:计算机网络、操作系统、数据结构/算法,这些东西都是专业课好好学即可,数据结构/算法可以偶尔刷题。校招的时候再重点复习,初级阶段不必花太多时间深究。
应用:它是最基础的内容,不管你从事什么领域都将离不开它们。这也是小白入门重点花费时间的地方,你将在这里不断与程序斗争如调试、验证、异常、解决。
方向:不同方向本质上就是在基础应用上扩充,发挥它们擅长领域和特性去解决特定问题。在这里,简单列一下涉及的技术栈。
- 后端开发:消息队列、缓存、rpc、微服务。
- 大数据开发:Hadoop、Spark、Storm、Flink
- 自动化运维:elk、ansible、zabbix、docker、k8s
04
基于上述分析,主要讲了整体思路,大家可能会觉得有点不太好理解。接下来,拿我当时遭遇的处境进行举例阐述,这样让不同水平或时期的同学有不一样的体会。
假如有时光机让时间往后倒退3年,时间来到我刚上大二的时候,作为一枚小萌新开始学习JAVA走上后端开发之路。
对于我来说,操作系统原理、计算机网络先战略性放弃,毕竟刚接触编程,看高大上的原理,每次上课都想睡觉。当然,数据结构/算法我还能好好听听,毕竟我数学功底还行让我不排斥。
为什么不先学习基础性原理?
举例:假设你学骑自行车,你是直接上去就蹬?还是先把轮子拆下来研究清楚原理再去学习怎么蹬?
重点:根据我的经历,在新手阶段不管是接触新的语言,还是新的方向。最快的方式就是先把自行车蹬起来,等你蹬熟练了再去研究轮子是怎么造出来的。
根据上述策略,刨除我踩的一些坑,我把学习征途划分四个阶段,实现学习效率的最优解。
第一阶段:新手入门
在我入门的时候,我遇到的最大困难是代码不会写,DEBUG不会做,程序报错不会看毫无头绪,甚至大家常说的百度一下的关键字我也不知道搜。
这时候,最大的目标就是根据百度/查文档/看视频,把程序调试出预期结果,甚至你抄代码都行,很多时候抄代码你都不一定能DEBUG出预期结果。这就是现实,主要就是要把对编程的排斥消磨殆尽。
这个阶段,不需要太关注底层实现原理,最重要的工作就是把应用层面的技术,不断练习直到熟练掌握上面提到的应用纬度「 编程语言、Linux、数据库、HTTP网络协议 」。
- 时间:3-6月
- 目标:会调试、会查文档、会用搜索引擎
- 内容:JAVA基础语法、MYSQL数据库、Linux操作系统、HTTP通信协议
- 方法:只关注如何使用技术,难以理解的背下来,不关注底层原理。
- 成果:实现常见的管理系统模块,能部署在服务器上,供他人访问。
对于现已从事计算机行业的同学,其实这部分内容非常简单,可能按照正常水平少则几天,多则不超过一周就能开发出简单模块。简单说,它顶多是普通本科毕设设计水准,主要是让新手在感官上体验软件产品。本质上,在计算机世界里,抽象来看就是数据的计算、传输、存储。随着你的经验增多,你会发现很多技术都是诞生或优化性能都是在解决计算、存储、传输的问题。
在这里,主要让大家在系统的角度感受最简单、最初级的技术模型。
- Linux操作系统:承载应用程序、数据库的运行,提供CPU供应用程序计算。
- 应用程序(Java/Python/Php):JAVA主要采用Servlet、JDBC承载网络的传输、数据库连接管理。
- 数据库(MYSQL):主要理解关系类数据库的存储,对数据进行操作。
- HTTP/TCP:熟悉重点网络协议,它分为包头/包体进行传输,包体格式可能分为form、json、pb、二进制。
第二阶段:项目练习
通过第一个阶段学习,你对编程从一无所知到有所斩获,对计算机世界充满了好奇,甚至有所开心。这时候,你最应该做的就是去满足你装逼的梦想。
假设你是爬虫方向,你应该去爬表情包、爬知乎数据、自动抢票,去满足你无数个装逼梦想。
假设你是算法方向,你可以去研究推荐算法、图像识别模型,去做个商品推荐、人脸识秀一秀。
假设你是后端方向,你可以去研究下网络编程/网站开发开发个仿微信聊天应用,体验下lowB版微信。
画外音:多做项目,坑是一步一步踩出来的。
作为大学生,实验室、软件设计比赛、开源社区都是你发挥现象力的天堂,这些倒腾的经历将是你毕业时最宝贵的经历。
第三阶段:强化理论
经过前两个阶段实践,时间来到大三,这时候基本的软件开发已入门差不多达到普通培训班毕业水平。同时,专业课如数据结构/操作系统/计算机网络也上的差不多了,对概念多多少少有初步了解。
这时候,你会发现很多原理你不懂,将很难更上一层楼。
- 你不知道使用ArrayList还是LinkedList?
- 你不知道为什么要使用线程池?
- 你不知道为什么分层设计使用分布式场景?
你将处于写代码一时爽,一直写一直爽,遇到性能问题直接土崩瓦解。所以,你不得不去学习理论知识让你走得更远。
问题:为什么在这个阶段强化理论知识?
在新手阶段去强化理论知识,会让你兴趣骤减且产生学了有何用的错觉。同时,这是最好的时机,学校专业课学完你有基础概念,你有实际软件应用场景,这些东西让你深挖理论的时候会快速给你构建起基础图谱,让你兴趣激增不断体验学会的东西,将戳痛你最痛的神经,瞬间把你以前遇到的问题有新的认知,这就是答案。简单说,面向问题,解决问题,让你实实在在感受到成长,这就是成就感的力量。
问题:如何高效的学习理论?
其实,编程语言和计算机基础都是相通的,只要你学透一门编程语言剩下的就大同小异。当然,计算机基础毕竟是枯燥无味的,学习毕竟是有方法的。
举个例子:
站在编程语言的角度,你用心去总结,你会发现不管什么编程语言,变来变去都是换了个花样在谈以下内容。
- 程序结构(数据类型、控制语句、面对对象、异常处理)
- 集合(list、set、map)
- 文件操作、网络通信(io、bio、nio)
- 线程、线程池
不管在面试还是技术探讨,重点考察的都是集合、网络通信、线程/线程池。源自于它跟计算机基础有紧密结合,你要优化它们你必须具备扎实基本功。
基于我的研究经验,我建议大家在学习计算机基础的时候,不要因为理论而理论。你应该去通过编程语言源码去学习计算机基础,只学你当前认为最重要的。
举个例子:
当我去学习数据结构/算法的时候,我会一边学习源码一边思考数据结构,这样就让我有实际应用场景不会因为理论而理论。我学习list、set源码的时候,我就学会链表、栈。我学习map的时候,我就学会了红黑树、散列表。
当我去学习计算机网络的时候,我会一边学习socket的用法,学习Linux网络通信模型epoll,这样就重点把网络协议学会了。同时,很多应用场景极少的理论知识,我就粗略记忆或者跳过,这样就节约了很多时间。
当我去学习线程/线程池的时候,我会学习锁机制、生产者/消费者模型这些操作系统原理的重要知识,跟编程语言中关联不大的我就粗略记忆。
第四阶段:深究专长
经过前面三个阶段的学习,你已经具备扎实基本功和项目实战经验。接下来,你需要做的就是更加的专业化,研究一些有生产意义的东西。如果你一直写学生管理系统,这些没有价值没有意义的东西,那么毫无意义。
这时候,你应该去互联网公司验证你学习的技能。除此之外,你可以去学习额外的成熟先进技术栈。这样,你就有实际业务经验,就有技术的宽度,同时又有深度,这就是你核心优势,毕竟算法/数据结构这些东西在竞争的时候大家都会。
画外音:去实习,最好去大厂实习,接受互联网软件开发的挑战。要是不能,那么去研究实际企业技术栈的应用与底层研究。
举个例子:
假设你是后端开发,你就可以去学习微服务的技术栈,springboot、dubbo、docker、hadoop都可以去学习。除此之外,设计模式,redis原理都可以去学习研究,只有这样当你去面试的时候,你有很多话题和故事讲给别人听,你的专长研究既可以让你说业务场景,你又可以讲底层原理,对答如流。
05
经过上面的训练,已经具备了解决问题、快速学习、编写代码能力,也就是具备软件工程师的职业素养和扎实基本功。
这时候,进入互联网公司开启职业道路,你将会很快有产出,不会陷入徘徊自闭的状态。更何况,你的职业素养已经能够让你遇到问题,能快速的学习克服困难。但是,要是让你去参加面试可不一定能独善其身,毕竟工作拧螺丝,面试造火箭可不能疏忽大意。
接下来,重点讲一下如何应对面试?
面试也就是把自己卖出去,让别人觉得你值。简历是至关重要的环节,所有的知识和技能全都是围绕它展开,否则毫无意义。因为在面试中,面试官关心你有什么,也就是面试完全围绕着你会的东西展开提问,所以你就把你的优势发挥到极致就行。
环节一:准备简历
简历一定要认真对待,一定要简介精炼,尽可能把内容压缩到一页,毕竟简历筛选就30秒不到。这时候,简历排版、简历字体、简历模板都有讲究,细节决定成败。
在写简历的时候,主要分为个人资料、实习经历、项目经历、专业技能。其实,没什么技巧,参考STAR原则,重点体现你在项目中的价值和思考。
- 要体现做了什么事情?
- 遇到什么困难?
- 怎么解决的?
- 产出是什么?
假设有读者需要简历模板,可关注提供给大家。
环节二:梳理知识体系和刷面经
以前,学习知识是零散的,学习策略更多是面向解决问题,以至于知识不系统,表达逻辑层次有限。面试官逻辑思维强,所以你必须做好充足准备才能脱颖而出。
最好的策略就是梳理知识体系和准备面经,我们都知道要是你面试官问的问题是你刚好熟悉的问题,你岂不是轻松闯关成功?所以,准备考纲、梳理知识体系、疯狂刷题这就是最好的策略。
按照互联网面试流程大多数分为三轮面。
一轮面试:主要是考察计算机基础知识和擅长语言基础知识,重点考察数据结构/算法、网络编程、擅长语言基础。但是,绝对不是死记硬背的东西,一定是深度和广度紧密结合,环环相扣直到把你肚子里的东西全部挖出来。
举个例子:
- 获取链表倒数第N个节点的值,只许遍历一次。
- 有一个1G大小的一个文件,里面每一行是一个词,词的大小不超过16字节,内存限制大小是1M,返回频数最高的100个词。
- 谈谈HashMap,说下它们的数据结构?
- Key在HashCode取余以后,它可能全部堆积在某几个Key对应的链表上,这样就会造成该数据结构存储或者查询低效,那怎么解决呢?
- 为什么会链表要变成红黑树,什么时候从链表变成红黑树,什么时候从红黑树变回链表?
- 假设多个线程并发访问,那可能造成容器更新或者操作出现问题?
- 除了使用synchronized加同步锁,还有没有其他办法解决呢?
- 为什么采用CAS,能说一下ConcurrentHashMap的具体实现吗?
你会发现每个问题都是环环相扣,从简单到难,目的就是挖掘出你的极限。大多数情况都是,从数据结构/算法入手,扩展到编程语言特性,再扩展到并发/网络编程不断进行深挖。当直接问实际用法应试者答不出来的时候,就会再次引入到计算机基础知识,这样不断反复调度试探应试者的是深度和广度。
二轮面试:这轮考察实习/项目经历,重点考察你的面试储备。众所周知,大部分应届生项目经验十分有限,大多数是图书馆管理系统、电商系统这样。重点说一下应对策略,可以去网上找你做的项目可能遇到的领域难题,去找解决办法,最终扩展补充到你的项目中。
三轮面试:这轮面试更多是经理考察应试者的基础能力。也就是逻辑思维、抗压、时间管理等基础能力,看下是否能融入团队,毕竟适合团队的才是最好的。
这里主要讲了思路和应对策略,至于篇幅有限,面试题只能读者自己梳理,假设有需要后续再聊。大体的思路:
- 梳理知识体系看面试可能考哪些东西?
- 去网上搜寻和整理面试题?
- 把数据结构/算法、并发编程、网络编程串联起来,还要学会理论知识和实际实战中来回串联。
总之,作为普通学校的同学,你只有花更加多的时间在项目实战中,实习/打比赛/逛开源社区,这些时间让你更快接近成为职业软件工程师。当机会来临的时候,你抓住机会就踏入大厂的大门了,幸运永远不会无缘无故眷顾你。