编程十年
先放一些之前为公司整理的前端学习资料吧。内容有点旧,有些排版有问题,将就下吧。希望可以帮到热爱学习但没有找到好的方法和资料的人:
C#、DotNetCore(待定)
回首10年前用VBA写记账软件,到现在走过的点点滴滴,略多感慨,稍总结如下:
1 何为编程
这是一个小马过河的问题。去问算法大神,去问CRUD程序员,或者就算同一方向不同技术路线的人,得出的答案可能都不一样。
这个问题的答案不在于别人,而在于你自已的心——编程对于你而言,它是什么就是什么,让你感受到什么就是什么。
2 怎样才能写好程序
一路走来看来,觉得最重要的还是:兴趣。
我见过有兴趣没天赋的,也没过没兴趣有天赋的人,但最终还是有兴趣的人的程序要写得好一些,更不用说平日的管理成本了。
也许你想看到诸如:学习能力、记忆力、分析能力、抽象思维……之类的占比,请相信我,那没有意义,也帮不了你,甚至会唤起一些人莫名的骄傲和自卑情绪。
编程是生活的一环,好的生活不就是喜欢什么然后去做么?
之前遇到一些同事,赶上了那波互联网泡沫。工资体面,但他们是由衷的不喜欢也不擅长编程啊。有一个很要好的一个朋友,很长一段他处在一种:学不进,团队不认可,无法晋升,转行没底气的状态中。你知道那是一种怎样的煎熬么?
3 我认为的有趣
帮到自已或别人的成就感;
程序的结构之美;
创造或突破一种解决方案时的灵光;
解疑找到问题所在时的爽;
一点点超越原先的充实;
4 心法至上
要想长久的保持进步,在首先要养成良好的心态:
- 保持对编程的兴趣。找出你认为编程有趣的点,想办法跟自已强调它。比如你觉得解决问题有成就感,就多和同学或同事讨论下问题,解决了可以获取多倍成就,没解决也可以学点东西;如果你喜欢"探案",就不断给自已假设各种可能性,去一一拆解;如果喜欢程序的结构,有空可以强迫症似的不时重构下原生的“屎堆”——趁它们还没长成“屎山”。
- 锻炼遇事不急的习惯。我以前也总想着“毕其功于一役”,但最后还是被“问题是解决不完的”打了脸。客观的需求似乎永远在跟你打太极,要让自已别太急。太急了解决不了问题,也会让你的领导对你印象扣分。
- 注重基础,或做好长期打算。不做长期打算的人会怎样呢?盲目追求新技术,东学一点西学一点的,最后可能能ABC的发音都没搞准。基础是什么呢:常用快捷键、常用API、常用配置、常用语句、常用的数据结构、常用处理问题的思路、经典算法、常用工具、使用框架的基本原理等
- 锻炼穷根究底的习惯。(脑中不友好的出现部队训练狗子咬着轮胎不松口的画面)。是的,一旦嗅到丝丝疑惑,力所能及的范围内一定要追查下去。你是程序世界的国王,你可以把事情查清。抱着满心疑惑求证的人,是最有行动力的。一次次求证的过程也是一次次学习和突破原有局限的过程——学习能力和分析能力往往是这么来的)——而且你解决问题的能力越强,领导才越敢把你放在重要的位置,你才越能服众,不是么?
- 尽可能追求优雅。追求优雅有一个层次的,追求它的过程也是一个程序员健康成长的过程:风格、准确精简的使用api、常用写法和算法、常用的结构、常用的第三方、己方库和第三方的整合、运维和部署。
5 业务至上
本来它应该属于心法之一,但过于特殊,所以单独列举。
以前问我业务和编程能力哪个重要,我肯定会说编程能力。但现在我感觉业务理解还是更重要一些,领域越深越如此。
“程序”是什么,就是用来帮人们解决现实中的问题的。所以,业务决定了你写的东西是否有价值。技术不行多数只是换个差点的技术方案慢一些,但如果对业务理解或把握得不准造成产品无人问津,团队会损失钱和宝贵的市场先机。
或许你会说,需求不应该是产品或项目经理的事么?不理解需求直接问他们不就得了么。这里要说两点:
一、深入理解业务需求,可以帮你找到更好的思路。有没有这样的经历,很多时候,一个项目写着写着你觉得越来越简单了,回头看之前的代码,发现好多逻辑代码根本不用绕那么多。对业务需求越深,你转化的代码就越强健,代码本身就是一个把需求转换成思维的过程,脱离需求就不叫程序了。等你可以预备到将来需求的改变时,就差不多到专家组别了。
二、理解需求可以锻炼自已的设计能力。设计能力只是划分几个模块几个类几个接口么?NoNoNo。举两个例子,大家都写过日志,也接触过事件吧。
如果让你搞个写日志的模块,你要设计哪些功能,由哪些类承担,由哪些接口对外公布呢?
你要考虑哪些,我们一起思考下:
1 日志存放在哪(db? 控制台? 文件?http发送出去给其它模块写... 可否动态配置?) ;
2 日志除了你放的message还要记什么?(程序名?版本?时间? 创建人? 堆栈信息? 环境或设备信息?线程信息?);
3 那些信息以一种怎样的格式展现呢?(既美观又好搜索,可否动态配置);
4 如果写文件中,线程并发怎么办,都写一个文件太大怎么办? 如果写http中,发送太频繁怎么办?如果写db,elashticsearch还是sqlite, 还是?
...
如果写事件模块,我们也可以思考下上面的问题:
1 事件怎么添加,怎么触发,什么时候触发,如xxx.AddEventListener(key, callback), xxx.RaiseEvent(key)。那么,事件的回调函数存放在哪呢?
2 事件的参数怎么设计,要不要放sender?设计成什么类型?
3 事件可以传递吗?传递过程中可以取消吗?
4 有些事件我只监听一次的,可以ListenOnce么?
5 有的事件只能订阅一次,有的可以多次订阅,是设计不同的api,还是之前的listene放不同的配置参数呢?
...
或许你会说:我在教你造轮子。如果未来你做了团队技术负责人,你能保证你能永远都能找到颜色、重量、轮子纹路、螺丝大小位置,适用场景都刚好匹配的轮子么?
其实,你知道么?让你不要重复造轮子这句话并不是为你好,而是怕你浪费团队效率而已。
如果你连轮子都不会造,未来怎么保证可以造车呢?你该不会觉得架构师就是像郎中抓药一样,把各种自已和和第三方的轮子配起来就是一个好系统了吧。他需要了解每个零件的细节,以使整体和谐。在时候可能要把一些零件削一削,有时候可能还要打点补丁,有时候可能会加点润滑剂,如果一些零件太有棱角不好改进又不没什么好的替代,就只好自已造了——而了解轮子最根本的方法,还是自已把它造一遍。
6 方法论
对的,光有内功还不够,你还是想听一些关于招式上的,可执行的方法和建议, 随机总结一些吧:
- 注重笔记。什么叫好的笔记呢?如果你能做到一个问题或知识点,80%左右第二次不用查原资料就及格了。早些时候我用过市面上可以下载到的几乎所有的付费和非付费云笔记,各有所长,最终选择了网页剪辑能力好一些的为知(我网页查得多)。笔记工具没有好坏之分,自已用得顺手就行。比如现在我看开源多一些了,就自已写了一个笔记工具,最主要的原因是用它做插件可以直接把vs里的代码右键添加到笔记中,同时可以记录下笔记所在项目、文件,行等。
- 立足当下,稳步拓展。当下可能是你所在项目所用到的技术,也可能是你自已在研究的课题。当下的课题才是自已的大脑热点,只有够热的区域才有灵感迸发的可能;只有替团队解决当下的问题,你才是有价值的。如果见到一些人当下做不好,总抱怨这那的,甚至说自已想换个领域的,真给他换个地方十有八九还是做不好。
- 重点优先, 先出成果。没有必要把一门技术学到100%再学另一块。用不到的技术,放在真正的教课书里就好。以学习前端为例,在培训的时候,我给团队的定学习路线大约是:css(20%) -> js(30%) -> angular(20%) -> css(40%) -> js(60%) -> angular(40%)。其实angular掌握到40%,已经基本上可以窥见技术路线的概况,也可以开始干活了。他们没掌握的余下60%中的内容,由技术骨干或者我来负责就行了。这和立足当下也是一样的道理,我们先把当下用得着的css, js, angular知识学会了,再一点点加深就好了。先出成果既能激励团队成员(因为自已创造了价值),又利于团队出成果甚至赶进度,一举两得。
- 基础优先。 除了心态篇上说的基础,这里更指基础思维。大框架可能变得很快,细分的基础思维则不会。比如早年间ajax刚出的时候,用了一段时间后就想,如果一直请求ajax,然后替换界面的html,是不是就可以不用刷新页面了——后来出现了angular之类的单页面程序;学习了html做winform的时候,就想,每个控件单独设置样式太麻烦了,有没有像css那样可以全局起作用的呢?wpf中的style文件就有了;ado时代就,一直操作表格太麻烦了不OOP,能不能把读出来的数据转成object。存的时候自动把object转成table呢,后来出现了ef;“绑定思维”在winform时代早有了,wpf中更加强化了,在前端三足鼎立之前又出现在了一些小框架中如knockout.js,现在前端三大框架也都有了;早些时代的java:依赖注入,方法拦截,现在的asp.net(core)已经自带了;.net的linq和一些新语言特性,在java和其它语言中也能见到……如果面试WPF,面试官让你给他讲讲MVVM,你说winform的实践中你已经实践过自已的MVVM框架,你觉得他会怎么看你?以前WPF是新框架不假,但它的思路未必是全新的。
- 不定期给自已或团队写点小tool,无关进度无关考核,只为单纯的满足下写代码的乐趣:比如上面的vs笔记插件,或者某款单机游戏外挂,或者团队某个数据转换/查询工具等,代码生成器什么的。
- 多和其它人讨论问题,不管比自已水平高还是低,有助于帮忙自已从不同角度看问题。
- 重构。没时间就挤时间重构。时间少就小规模重构。时间多就大规模重构——没什么方法会比重构让你进步的效率更高。
- 能自已查资料的就别请教,能用英语查的就尽量用英语——英语不行就,每天上下班的时候背嘛,扇贝走起。
- 打字速度尽量练习得快一些,高手抽出时间从自已工作中切换出来指导你已经很可以了,别给他们表演“找字母”。
- 觉得遇到瓶颈期了,就想想平时遇到的一些硬骨头试着解决,说不定那些那就是你突破的方向。
- 文风。别以为文风就是大小写命名对了,方法大小划分合适了,如果对自已要求严格一些,很多东西可以做得很细。就我个人而言:
- 能嵌套少的写法优于嵌套多的写法;
- 减少无用信息,如C# if(xxx==null){throw xxx} 可以写右 xxx = xxx ?? throw xxx;js if(xxx==true){exp()}可以写成 xxx && exp()。初学者可能不太习惯,但写多了就会决得这和听人讲话不喜欢太多无用言辞是差不多的道理,而且读if条件视线增加的换行切换也是一种代价;
- 当代码中逻辑比较多的时候,自已适当“分一下段”,写完一层意思空一行后再写后面的一层意思。常见的赋值语句写完后空一行写下面的逻辑。这样别人读你的代码的时候,不会因为大量代码不空行叠在一起太有压迫感,读一层意思空一行,让读者或自已无意识稍休息下,更利于舒服和好理解一些
- 如果觉得一件事简单,就对自已提高要求和留心学习下别的。之前去过一个很大的外包公司,那时工作对我来说有些枯燥和简单。知乎上很多被外包坑过的人几乎仇视外包公司了,那一阵我同样学到了很多在之前公司没见过的东西,比如我利用空闲时间研究过美国团队写的领域驱动架构(那个时候领域驱动在国内还不流行)。曾经接到一个winform的程序,3-4天的工作量,组长给我争取了10天,我就把依赖注入等高级特性列了进去研究和学习了微软的开发库,当时还利用刚学的LinqExpression写了绑定框架来练手——我们都喜欢无意识偷懒,兴趣能让我们逆流而上。
- 保持阅读,最好是英文的。一些人对外包公司有对外包公司有偏见,但当时我还是遇到了不少优秀的同事的。比如有个哥们每天来得很早,在会议时间之前,他雷打不动的会阅读一些技术文献。我那些刚入行1年半,这一年半我每天都会阅读codeproject上的文章,有时候是来得早还没安排活先读着,有时候是查东西,有时候可能是在来回的路上。阅读开阔了我的眼界也迅速掌握了不少术语,听Leader他们讨论问题感觉就是不懂的越来越少了,有时候我还可以给他们一些建议:比如很当时给公司建议利用chrome内核+网页技术做桌面应用,改造当时的一个BS项目;知道了常用术语的表达,google查东西的浏览也快了很多。
7 学习教材
教材一般有以下几类:
- 官方api文档 + 官方教程。全面,但示例比较少,内容发散——适合查找或专题学习。
- 博客。博客往往就一个专题讨论的比较多,系列教程的也有,但还是偏专题性质——没错,很可能你是问题解决不了或想不起来,然后搜索过来的。
- 书。书适合系统学习理论,或者对某个技术框架有一定了解后查漏补缺用——千万别以为看书 == 会了或 看书 == 了解了。
- 视频。视频个人觉得当专题时信息密度不如博客,当教程时又不如书全,除了一些资料只有视频,一般我不做优先选择。当然,对于一些不太喜欢通过文字汲取信息的人,视频显然更好一些。
- 源代码。开源代码适合有研究精神,有能力,而且有需求的人学习——但公司内部的代码,显然就相当适合新手学习了(不了解需求看源代码,几个if-else就可以把你的思维甩丢,但公司的项目就不会不了解需求了)。
个人觉得,初学还是找一个相对忙,能接触的面广一点,管理宽松但不混乱的企业,在项目中学习效果最好。长久的看,它们没有好坏之别:毕竟,看了不等于记住,记住了不等于会用,会用不等于会写,会写不等于会设计——每隔一层,“教材”的作用就少了很多。
又要提到了那个好友了,前面不是说他心态很煎熬么?那一阵他每天看买来的各种书和视频,他真是看了也记不住,记住了用的时候也想不起来——于是更加煎熬了。说到这,我是很有些痛心的。
8 我的学习方法
- 先泛读语言特性和框架特性,跑或写写基本的demo,知道这门框架可以基本做什么。
- 最常用的是专题性的学习,我会设置一些专题,然后查找一下专题相关的资料。比如刚学习js,html, css时,尝试了写两个控件:日历控件和导航树。我先找了两个例子,研究了下别人的思路;然后总结它们的实现原理和关键API(当时api还没记熟);然后根据自已写的总结,重新写出来——没错,我就是坚定的轮子爱好者。在重写的过程中,既增加了语言和API的熟练度,也通过掌握了一些框架特性,还有运用思路——这些东西积累到一定的量后,你会对很多东西,甚至是跨语言框架层面的东西,产生一种融会贯通的感觉。
- 经过上面的一步,有时候你再使用类似的第三方,就很容易猜出它的大致实现原理:学习和使用起来当然就更轻松了,还有调BUG也会很轻松。
- 有时候大的专题会涉及到几个技术的交连,那就拆分成几个小专题好了。于是,一个系统 == 很多专题。
- 偶尔我也还是会通读下官方文档或相关的博客专题,对自已已知晓的进行查漏补缺。
专题学习的好处是:始终带着问题,对研究目标抽丝剥茧,激发求知欲有动力进行下去。而且学习到的知识,是有机组合的一个整体,不是书本上零零散散的,抗遗忘效果要好很多。每个专题解决专门的一类问题,有成就感。不足就是框架体系中横向的知识可能会不够全面,有时候可能会限制你解决问题的思路,这就要通过相对系统的阅读和刻意的研究来弥补了。比如C#中,后来学到了Remoting命名空间的知识后,才知道IOC原来还可以通过它实现。在这之前只知道通过IL做,而且限制较多。
9 成长的阶段
一、交学费阶段。这一阶段最好大学就做好,认清什么是计算机,什么是语言,语言怎么工作的;什么是变量,什么是输入输出,什么是内存,哪些基本的算法;什么是OOP,什么是程序,什么是IDE……对编程能有个直观的认识,通过基本的练习,越具体越好。
二、框架学习阶段。这个时候你也许在企业,也许在学校做某个课题,因此要专门用到一些开发框架。框架学习阶段重点要学习框架的基本数据结构,以及相关API,如string, date;还有就是一些功能性的API, 如IO, 数据库等。可能还有一些相关的东西要学,比如语言特性、部署、团队开发管理、基本的程序分层结构等。
三、程序设计阶段。框架学习个1-2年后,会进入第一个瓶颈期。你觉得API都会调,常用功能也都能实现,但写一个项目心里没底。api也只是会调而已,离开了api你可能什么都不是,你沮丧的叫自已“api caller"。要突破,你需要掌握或加强一个新的能力,设计能力。这个设计能力不是指架构设计,而是能把大的问题拆分,细化成一系列小的解决思路。有时候可能会用到一些算法,或数据结构的使用。随着自已开始注重实现,你偶尔也会研究下api中一些东西是怎么实现的,如反编译或查开源代码。渐渐你觉得程序有趣了起来,如果你好奇心比较强,就会发现有很多以前自已模棱两可的东西,现在想去搞清楚,或自已实现一下。设计阶段的持续时长因人而异,半年到2年甚至永远无法毕业的都有可能。
四、第三方收集者。团队要求设计能力,却往往强调“不要重复造轮子哟”。比如List明明有Remove方法,你不知道,偏偏每次都要自已写;自已写就算了,还不知道封装,是不是等着被训话呢?这个时候,你不禁好奇设计的边界在哪呢?答案或许会让你很沮丧——几乎没有什么值得你设计的,需要你设计的不是在第三方就是公司的我方库中,能找到轮子!如果你是“一些人口中的CRUD”程序员,可能轮子都不太用得到,一大堆if-else后,更新数据库就好了。于是,你开始汲取上次擅自设计每训话的教训,留意起框架中的冷僻api,以及一些常用第三方。突然,你开始对第三方感到amazing!,于是渴望知道了了解更多的第三方,甚至以此为傲。这个阶段是提升一个程序员眼界的阶段。它不一定在设计阶段之后到来,也可能与之并行,持续整个职业生涯。
五、模块负责人。很快你又遇到了新瓶颈,现在你不叫自已“api caller”了,你叫自已“3rd caller”, 你想:也许离开了第3方,你就什么也不是了,怎么办呢?突破方法,这时你忍着挑战“不要重复造轮子”的想法,开始自已挑战一些有可能重复造轮的事情。等造了几个简单的轮子后你发现:1轮子并非自已不能造,只是不用花这个时间而已;2轮子中考虑的很多细节,其实在你的项目中是用不到的,它的轮子可能有点重。这个时候另一个信号出现了,为了打造高质量的轮子,你开始更加注意自已的代码强健性,开始研究代码整洁之道,强健之道(设计模式)等 。原来轮子也没那么神秘,渐渐的,这个瓶颈期的焦虑降了下去——后面你也不太轻易造轮子了:毕竟好多轮子你都能猜出怎么造出来的了。这个时候,公司偶尔有一些需要新轮子的模块或项目,你会特别想去写, 虽然他们多半是和业务相关的轮子。私下你觉得造轮子是件很爽的事,因为模块上的注释中写着你的名字,后面的小弟都会来观摩学习。但让小弟造却是不太放心的,于是你对新来的小弟说:嘿,别重复造轮子哟。
六、项目负责人。模块写多了,分解任务的能力就更强了。1-2年左右,你以学会了套用公司的组织结构和开发管理流程,领导可能就开始琢磨让你完全负责一个新项目了。从现在起,你发现一些软实力的重要性了:对需求的理解和预测,对项目时间的估算,团队开始管理工具的部署(任务管理,包管理,源代码管理,团队wiki等),沟通培训,人员安排,运维技术等。 这些不一定会在你刚管理项目的时候就全部加过来,但会慢慢负责起来:能力越大,担的越多。
七、之后。这之后就取决于你自已的选择了:继续带着团队乘风破浪看身边人来人往?继续研究你的课题?还是做管理?
10 经典与潮流
程序界也和时尚界一样,有潮流的。去年朋友跟我聊起技术已经满篇都是区块链、大数据、AI、物联网、微服务之类的话题了。
我也曾为公司写过web端3D图形渲染引擎(体量超大)及相关应用。如今却满满的动力想把CRUD程序写好。
知乎现在已经成了比较浮躁的地方,之前还听到所谓的大神说:“如果你眼中的编程只有CRUD,请不要跟我讨论这个话题。"是的,如今我就是想把他们鄙夷的东西写好。
不是说CRUD不值得写,相反我觉得正是因为它容易写,而这么多年下来,在公司一直"临危受命"到处救火的工作,懂得看似很多,但让我给出一套"比较舒服"的CRUD技术方案(钟爱的.net core版),心里反而不是很有底,这才是不能接受的。
或许你会疑惑:为什么不学那些新知识呢?做为程序员,不是要一直保持学习么?面试“大”公司怎么办?这个行业一直有这样一个疑惑:技术一直推陈出新,到底什么时候,才能说对技术有底气了呢?
我觉得对技术有底气是不太现实的,只能对自已有底气。底气一来自自已的抽象思维能力:当你觉得很多东西的内在都差不多的时候,至少在这一方面就差不多算有底气了;二来看学习能力,当给你需求和指定好新技术(甚至都不指定,自已找技术),你能在很短的时间内理解新技术并用来把实际问题解决,就算ok了。
曾经我想把公司的面试题改为:告知bat命令的基本语法和必要api,让面试者学习后实现一个需求,比如文件压缩后ftp备份。想想公司的待遇和招人的要求,还是换成了一些简单的智商题。
曾经被迫进行过很多突击任务:比如1晚上学会js dom并仿写日历控件, 4天不出门学C++并做出消消乐的外挂,三天现学Asp.Net评估团队系统的可实行性,三天现学Grails接管新系统开发,两周内现学WPF和Revit的SDK写插件导出图形及材质数据,要求1.5个月内学会Angularjs并培训团队把站点做出来。也见过很多技术的兴起和衰落——技术永无止境,也许残酷,但这也不正是它有趣的地方么?
不要把自已定义在经典说时尚,不要把自已定义在不同语言体系,也不要把自已定义在不同的技术分支——技术是用来满足的求知和进步欲的,别轻易变成某个片面的信徒为其摇旗呐喊甚至斗争。
我们想学时就前进,想停下来思考时就停下,想试探下其它技术线的别有洞天就想办法去做。