程序员需要具备的基本技能
2011-03-14 10:14:39 阿炯

软件开发是一个跨度很大的技术工作,在语言方面,有C、C++、Java、Perl等等;在环境方面,又分嵌入式、桌面系统、企业级、WEB、基础系统,或是科学研究。但不管是什么的情况,总是有一些通用的基本职业技能。

这些最基本的职业技能通常决定了一个程序员的级别,能否用好这些技能,直接关系到了程序员的职业生涯。很多程序新手也是因为缺少、达不到或是不熟悉在这些基本技能,所以,他们需要有老手帮带,需要努力补齐这些技能。而高级程序员应该非常熟悉这些基本技能,而且有能力胜任并带领其他经验不足的程序员。这些基本职业技术可以用来做为对一个程序员的评估,很明显,下面的这些技能都可以用来做面试。虽然还有很多非技术的因素,但对于评估一个程序员的技术能力来说,其应该是足够的了。下面是程序员所应该具备的基本职业技能:

* 阅读代码 - 这个技能需要程序员能够具备读懂已经存在的代码的能力,这样的能力可以让程序员分析程序的行为,了解程序,这样才能和开发团队一起工作,继承维护或是改进现有的程序。

* 编写程序 - 编写程序并不包括程序设计。不要以为编程是一件很简单的事情,很多程序员都认为编程只需要懂得程序语言的语法,并把设计实现就可以了。但是这离编写程序还远远不够,使用什么样的编码风格成为编写程序员最需要具备的基本技能。能否使用非常良好的编程风格直接决写了程序员的级别。

* 软件设计 - 这一能力直接决定了需要吏用什么样的代码技术达到怎么样的功能,而系统架构设计直接决定了软件的质量、性能和可维护性。并不是所有的程序在这一方面都非常优秀,但每个程序员都需要或多或少的明白和掌握这一基本技能。

* 熟悉软件工程 - 每个程序员都应该明白软件工程是什么东西,都应该知道,需求分析、设计、编码、测试、Release和维护这几个阶段。当然,几乎所有的人都知道这些东西,但并不是每个人都很清楚这些东西。现在很多高级程序员都会混淆“需求规格说明书FS”和“概要设计HLD”。另外,程序员还需要知道一些软件开发的方法/论,比如:敏捷开发或瀑布模型。

* 使用程序库或框架 - 一个程序员需要学会使用已有的代码,无论是标论的程序库,或是第三方的,还是自己公司内部的,都需要学会做。比如:C++中,需要学会使用STL、MFC、ATL、BOOST、AC、CPPUNIT等等。使用这些东西,可以让你的工作事半功倍。

* 程序调试 - 程序调试是分析BUG和解决问题最直接的能力。没有人能够保证程序写出来不用调试就可以运行正常,也没有人可以保证程序永远不会出BUG。所以,熟练使用调试器是一个程序员需要具备的基本技能。

* 使用IDE - 学会使用IDE工具也会让你的工作事半功倍。比如,VC++、Emacs、Eclipse等等,并要知道这些IDE的长处和短处。

* 使用版本控制 - 一定要学会使用版本控制工具,什么叫mainline/trunk,什么叫tag,什么叫branch,怎么做patch,怎么merge代码,怎么reverse,怎么利用版本控制工具维护不同版本的软件。这是程序员需要明的的软件配置管理中最重要的一块。

* 单元测试 - 单元测试是每个程序都需要做的。很多单元测试也是需要编码的。一定要学会在xUnit框架下进行单元测试。比如JUnit, NUnit, CppUnit等等。

* 重构代码 - 每个程序员都需要有最基本的能力去重构目前已有的代码,使代码达到最优但却不能影响任何的已有的功能。有一本书叫《软件的重构》,每个程序员都应该读一下。

* 自动化编译 - 程序员需要使用一个脚本,其能自动化编程所有的工程和代码,这样,整个开发团队可以不停地集成代码,自动化测试,自动化部署,以及使用一些工具进行静态代码分析或是自动化测试。

当然,还有很多的基本技术也是非常重要的,比如:与人的沟通能力,语言的表达能力,写作能力,团队协作能力,适应变化的能力,时间管理能力,多任务处理能力,自我学习能力,故障处理能力等等。这里只是列举了和技术相关的能力,这些是程序最最最基本的能力,只要是程序员就必需要有的能力。

几十年的编码经验浓缩成的几条最佳实践


良好的代码更易于阅读、理解、调试和修改,最重要的是它的缺陷也更少。显然,编写良好的代码需要更多的时间,但是从长远来看,它也具有更多的价值,因为这降低了维护的成本,而且具有更好的可重用性。

事实上,我们可以将好的代码等同为可重用的代码,这也是本篇文章罗列的许多技巧背后的驱动原则。作为一个要实现特定功能的开发者,代码可以实现你的短期目标,但如果没有其他人希望重用它(包括未来的自己),这些代码一定会缺失某些东西。无论它是太复杂,还是太具体,在不同情况下都有很大可能会出错,或者不被其他开发者信任。

我发现,只要尝试坚持将下面的最佳实践应用于你编写的所有代码(包括你的实验和原型),无论你现在的经验水平如何,都会编写出更好的代码。

1. 遵循单一职责原则
函数是程序员的工具中最重要的抽象形式。它们能更多地被重复使用,你需要编写的代码就越少,代码也因此变得更可靠。较小的函数遵循单一职责原则更有可能被重复使用。

2. 尽量减少共享状态
你应该尽量减少函数之间的隐式共享状态,无论它是文件作用域的变量还是对象的成员字段,这有利于明确要求把值作为参数。当能明确地显示函数需要什么才可以产生所需的结果时,代码会变得更容易理解和重用。

对此的一个推论是,在一个对象中,相对于成员变量,你更应该优先选择静态的无状态变量 (static stateless variables)。

3. 将“副作用”局部化
理想的副作用(例如:打印到控制台、日志记录、更改全局状态、文件系统操作等)应该被放置到单独的模块中,而不是散布在整个代码里面。函数中的一些“副作用”功能往往违反了单一职责原则。

4. 优先使用不变的对象
如果一个对象的状态在其构造函数中仅被设置一次,并且从不再次更改,则调试会变得更加容易,因为只要构造正确就能保持有效。这也是降低软件项目复杂性的最简单方法之一。

5. 多用接口少用类
接收接口的函数(或 C++ 中的模板参数和概念)比在类上运行的函数更具可重用性。

6. 对模块应用良好的原则
寻找机会将软件项目分解成更小的模块(例如库和应用程序),以促进模块级别的重用。对于模块,应该遵循的一些关键原则是:
尽可能减少依赖
每个项目应该有一个明确的职责
不要重复自身

你应该努力使你的项目保持小巧和明确。

7. 避免继承
在面向对象编程中,继承 —— 特别是和虚拟函数结合使用时,在可重用性方面往往是一条死胡同。我很少有成功的使用或编写重载类的库的经历。

8. 将测试作为设计和开发的一部分
我不是测试驱动开发的坚定分子,但开始编码时先编写测试代码会使得代码十分自然地遵循许多指导原则。这也有助于尽早发现错误。不过要注意避免编写无用的测试,良好的编码实践意味着更高级别的测试(例如单元测试中的集成测试或特征测试)在揭示缺陷方面更有效。

9. 优先使用标准库而不是手写的
我经常看到更好版本的 std::vector 或 std::string,但这几乎总是浪费时间和精力。一个明显的事实是 —— 你正在为一个新的地方引入 bug,其他开发者也不太可能重用你的代码,因为没有被广泛理解、支持和测试。

10. 避免编写新的代码
这是每个程序员都应遵循的最重要的教诲:最好的代码就是还没写的代码。你写的代码越多,你将遇到的问题就越多,查找和修复错误就越困难。在写一行代码之前先问一问自己,有没有一个工具、函数或者库已经实现了你所需要的功能?你真的需要自己实现这个功能,而不是调用一个已经存在的功能吗?

写在最后的话
我发现编程是一门与学习艺术或运动非常相似的技能,通过刻意的练习和从别人的经验中学习会得到更好的结果,不断提升产出的代码质量有助于成为更优秀的程序员。

也谈一谈程序员的职业发展路线


作为程序员,在开发岗位上做了几年,特别是到了30岁,这个而立之年,我们会来到一个重要的人生岔路口。就是管理和技术两个选择,一边专业路线,一边是管理路线。在互联网的头部企业,对管理和技术是平等对待的,所以晋升会存在管理和技两个通道的。


既然有了选择,就会有人纠结,不知道是选择专业路线,还是选择技术团队的管理路线。

这个选择是程序员人生中第一个大的选择,也是第一个障碍,倒不是说这个障碍是到底要不要选择管理,而更多的是对做管理的迟疑,怀疑到底能不能做好管理,做了管理之后,技术是不是就荒废了。

这种状态犹豫不决、摇摆不定的状态保持时间长了,最终会导致技术和管理都没做好,这是得不偿失的。为了解决这个问题,有必要分析程序员职业发展的路线到底有几条,分别需要具备怎样的能力,从而做到”手中有粮,心中不慌“


1、技术
技术类上,是有两个方向:架构师和技术专家

架构师他的侧重点是在“广”上,他主要负责技术的整体和架构,在业务上,需要有很深的理解,有丰富的经验,甚至能做到“走的桥比你吃的盐还多”。在技术上,能够广泛涉略,掌握的技术知识越多,内力就越加深厚。

我觉得架构师还需要三点必备能力,其一需要有极强的执行力,能够快速的给出合理的方案,推动技术落地。其二需要有极强的判断力,能够准确的找到复杂系统的疑难问题所在,就像武林高手,一眼就看出对方的破绽。最后还需要有极强的创新力,能够创造新的解决方案,解决现有技术难题。所以从程序员到架构师的成长之路,总的指导原则是:积累经验,拓宽视野,深度思考。

技术专家他的侧重点是在“专”上,这个就很好理解,就是在某个领域能够深入,能够熟悉其背后运行原理。不同的领域都会存在专家,例如:Java专家、前端专家、图像算法专家、Linux内核专家等等。专家相对架构师,更加专注,并不会考虑太多整体方案。所以从高级开发成长为技术专家,主要是扩展领域内的技术宽度,提升领域内的技术深度。因为领域也不是特别窄的一个面,而是包含多个技术面。

举一个例子:Linux内核专家,要想成为Linux内核专家,需要掌握,Linux CPU调度、内存管理、进程管理、存储管理、文件系统、设备管理和驱动、网络通信、系统调用、系统初始化等技术面。在每个技术面中,同样包含了很多技术点,这些技术都是知识盲区,所以需要提升技术深度。

2、管理
管理也分为了两个方向,技术管理和职业管理。顾名思义,技术管理更加倾向于技术,而职业管理完全抛开了技术,纯粹的商业方向。

技术管理:这个方向是程序员最自然的选择。大部分的技术管理者,在其从程序员转为管理岗位的时候,都是在领导或公司的要求下,被动的推到技术经理岗位上的,并非是自己当初有强烈意愿、主动去选择管理岗的。然后走上曼曼打怪进阶的路线,从技术经理岗到技术总监,带领几十号人的团队冲关,然后到成为技术业务部和事业部的技术副总裁,相当于CTO了。

技术管理需要在业务上有较深的理解,在技术上能够根据技术发展趋势,进行技术规划。在产品上能够极强的洞察力,进行产品规划。在团队加上能够规划团队建设、组织结构等等,所以这是综合素质的要求。

职业管理:职业管理者往往更加关心于整体产品业务的团队,不限于技术团队。比如某个事业部的总裁,或者是某个业务部的总裁。大家往往都听过某某事业部空降了领导,这个领导就是属于职业管理者,他的移动性更加强,能力更加通用。这个方向是可遇不可求的,有些人一辈子都不可能触及到。这个就是天花板上的别人家的楼板,你说难不难?

3、创业
创业这个方向上,一般是作为技术合伙人来参与,如果想要自己的创业公司能够成功,必须是全能型创业团队,在技术、产品、营销等方面不能有明显的短板。

我举一个真实的例子:我的上一家公司的直接领导,辞去技术总监的职位,作为一个技术合伙人创建了一个团队,主要提供物流解决方案。前几个月和他聊,公司已经在去年实现盈利1000多万,通过股权上操作,已经成为最大的股东,掌管着整个公司的前进方向。

说到这里挺惋惜的,创立之初,当时极力的拉我入伙,被我拒绝了,理由是工资太低了,这个理由在现在看来简直可笑啊。

4、其他
项目经理

这个方向也是程序员比较常见,也比较自然的方向。项目经理其实一种组织整合能力。不同于技术管理,这条路线走起来,几乎不需要任何外界依赖因素。最需要关注的是进度、质量、人力、成本、风险。那如何提升项目管理能力呢?

首先需要对项目管理知识框架有个大致的认识,避免在庞大的知识体系中迷失方向,比如:
范围管理:项目为何总是做不完?范围管理要界定
风险管理:项目风险引发的问题、成因以及防范方法
沟通管理:做好项目沟通计划
质量管理:加强项目质量
时间管理:项目进度控制
成本管理:产品成品控制
等等

其次需要掌握项目计划、项目变更、项目进展报告、复盘等过程方法。最后需要掌握跨部门协作,多维度沟通上进行加强。

产品经理
程序员转产品经理,需要做到技术思维到产品思维的转换。技术思维角度是从功能开始,而产品思维的角度是从业务开始。

作为程序员,当要做一个项目时候,我们最关心的是这个项目有哪些功能,然后考虑每个功能如何实现;而作为产品经理,当要做一个项目时候,我们看重这个项目的业务场景是什么,解决用户什么问题。
 
技术思维角度是怎么去实现功能,而产品思维角度是为什么要这个业务。

从技术思维的角度关注一个需求时候,总是先关注一个需求如何去实现,即HOW;而从产品思维上来关注一个需求时候,应该多问一下WHY,为什么需要这个需求,多思考为什么,从而找到需求或问题的本质。

技术思维角度是向专家一样行动,而产品思维角度是向小白一样思考。

作为程序员,我们日常接触到最多的还是技术人员,这些人一般来说逻辑思维都较强,擅长使用和处理各种软件,所以总是将这种形象代入到客户身上。但作为产品人员思考时候,将用户想得越“小白”越好,假设他们是不懂电脑,不太会玩手机,甚至不会打字的人。

5、小结
上面4个方向是程序员主要的职业发展路线,作为个人来看,如果能一直做自己热爱的工作和喜欢的角色,应该是最好的状态。不管走那一条路,一些能力是共通的,比如:技术规划、团队建设、沟通、时间管理等。处于自己的选择,可能不会选择管理方向,但是难免在以后的工作中会和管理者打交道。管理作为一种通用的素质,希望大家能够技多不压身。总之,作为程序员,技术和管理,就像人的两条腿,所有的职业发展路线都离不开,毕竟一条腿是走不远的。

6、也说说一些编程学习方法
6.1、模仿
对于初学者来说最好的方法就是模仿。用控件写ocx搭UI,学HTTP协议,多线程,文件的保存和校验。当发现getright可以把下载任务打包成独立exe的时候,又去学习怎么样把URL隐藏在EXE资源里。看这个ASP论坛,那个PHP,PERL论坛,好热闹,就去sourceforge找代码,慢慢的学习CGI模式,脚本模式写C/S练手,又去学HTML4,CSS,还要用PS切图导出优化图片大小。 还要学习SQL语句,SP存储过程等等。

6.2、抄代码
把别人的开源代码,来回的看,看结构,看命名习惯,看指针的嵌套方式。看链表的实现,然后自己完全改个项目名称重新写过,把别人的代码按局部模块重新整理,添加没有的功能,砍掉觉得无用的功能。又或者去用不同的语言去写别人的模块的不同的版本,然后继续开源出去。

6.3、抄创意
去看别人在卖的软件或工具,然后试着自己写出同样功能的,然后开源或免费掉。不同的方法适合不同的人群,如果你是在校大学生,那么你有大把连续的时间,就先学习c,然后再学c++。了解c/c++和了解计算机系统是极为贴合的,向下可以帮助你更容易地理解操作系统、编译原理、计算机网络、计算机组成原理,而向上,c++面向对象的机制,也可以做出一些应用,譬如五子棋游戏等,也不会显得那么枯燥。可能学c和c++对你来说有些复杂和困难,因为学习它们确实是很需要时间。

学习还是要按照自己的实际勤快决定,适合别人的不一定适合自己。计算机专业的学生学校会陆续安排:数据结构,计算机组成原理,操作系统,计算机网络,软件工程,数据库,和专业课。

数据结构、操作系统,计算机网络,数据库这四门,会在你考研,保研、工作面试时,显得尤为重要。原因如下:首先,数据结构学得好的人,逻辑一定很清晰,代码一定会写的很漂亮,效率很高。因为想要学好数据结构,一定少不了实操,所以代码实现能力也一定就会很强。而操作系统学得好,才能真正理解多线程,才能搞并行。计算机网络学的好,才能理解应用开发时,为什么有前后端,前后端如何传递的信息。数据库学的好,才能知道数据怎么存储计算的。计算机组成原理虽然不如前三个那么重要,但学好了你就能更深入的理解,计算机如何运行的。基本上不会用到计组,但它有利于你在编程上发展的更深远。软件工程是最好学的了,而且你工作里很可能不会用到它。建议你按照以下顺序学习:C/C++ ->数据结构 ->操作系统->计算机网络->数据库->计算机组成原理->软件工程。

学习网络编程的建议

6.4、网络编程建议从Linux C开始做起,基于Linux 平台的socket API来起步,慢慢推进。写代码就用VIM,编译用GCC,部署用docker.如果还在大学,一定要好好上专业课。通过计算机网络课你知道所谓的协议分析是怎么一回事情。

6.5、Web编程要学习html和css,javascript一定要有所了解的,然后了解一下php。这些基本的东西网上有很多视频教程。去了解一些开源代码吧,从简单的emlog博客,到discuz,phpwind之类。有了基础,然后就开始怎么应用所学到的东西,如写一个简单的网站程序发布到各大源码下载站,当有人用你的程序后就会有人提出各种改进需求,如果你能想办法做出来,那你的网络编程就可以了。实在不懂有书可以自己买来看看《TCP/IP 网络编程》和《Linux高性能服务器编程》。前者绝对是新手村级别的书,书里的内容不会有过多的术语,作者都用大白话来表达,配图也很清晰,也有介绍网络框架,虽然是比较基础的多进程服务端模型、多线程服务端模型、异步 IO 模型。而且最后一章实现了简单的 HTTP 服务端,让人知道了从代码角度是怎么解析 HTTP 报文的,以及状态机是如何实现和运转的。

35 岁软件技术人员生存指南

介绍下对他人有用的信息,本人靠技术创业上岸,技术是我的能力基础。但取得的技术结果和商业结果,有着更广泛复杂的元素,比如运气至少占60%。文章最后会介绍自己在技术探索路上,起到里程碑作用的几本读物。

对软件人才可借鉴的经验:软件解决问题,需要三层:
(1)、理论知识     算法,数据结构,微机原理,操作系统,线性代数,离散数学,软件工程,以及与你工作相关领域最新的科学研究理论知识
(2)、技术     某种计算机语言熟练掌握使用经验丰富,或者某个领域钻研深入,类似图形,数据库,网络服务器,AI等等
(3)、工程     有限时间满足需求解决问题能力,与人合作开发的能力

第1层代表了你能够达到的上限,也就是今后技术发展的最高点。 第3层代表你的下限,决定了你35之后混得最差的底线。

第1层:理论知识

知识掌握越多,越新,越有可能扩展你的技术能力和工程能力。也就是掌握技术比别人好,工程问题你办法比别人多。比如对算法和数据结构掌握牢固,对操作系统掌握深入,当你要做尽可能压榨性能和内存的软件,你就可以从底层功能来解决问题。至少使用一些快速的底层工具比较顺利。比如内存管理,速度优化等。宏观上,对计算机体系理解越深刻,对软件质量管理理解越到位,你带领团队能做的软件规模和质量就会超过其他公司。你就成为某个公司的不可或缺的人。工资自然就比别人多。

绝大多数程序员的天花板就是底层知识不行。现在软件中间件和工具库太发达。一直满足用傻瓜工具和代码库,挣口饭吃。这种码农和那些工地搬砖的是差不多的人。35岁之后必然被淘汰。这一层决定了你以后最好的收入会在哪里。过去我喜欢看自己领域国外最新的论文。我发现和我有同样喜好的人,后来发展的都很好,钱也多,买房也不愁。不是说看论文就能买房了。。。只不过这个样本也许有点借鉴意义。说明对理论的持续补充,会增大你视野,尤其是解决问题的视野。

到了后期做技术管理,依靠的依然是底层知识+大量经验。理论知识就是得拼命看书,看论文。还得能融会贯通。

第2层:技的掌握

绝大多数年轻软件人员都在这一层。并且以数量掌握这一层技能为荣。某个语言,某个工具使用,某个图形技术。但实际上,有了第一层的理论知识,这一层就是一个砸时间去理解,记忆和熟练使用攒经验,小学生也毫无障碍。不太建议只拼这一层能力,虽然这一层是必须的基础。

第3层:解决问题的能力

有两个要素与解决问题能力相关:第一个要素是工程能力,这种能力是在前两层基础上建立的,比如我虽然瞎自学了好几年计算机;但毕竟有热情,比别人先耗费了大量的时间(几千小时),自然多积累了一些知识和技术。第二个要素是“对问题难度极限的感受”。

1)工程能力
拿自己举个例子:过去小学用机器码编程。这种比汇编还底层的指令编程,直接操作计算机的硬件。比如直接操作屏幕buffer,键盘输入。条件判断指令需要自己计算偏移量。由于机器指令编程难度极大且没有任何debug工具,所有程序逻辑必须完全在纸面全部验证完成,出了问题只能想各种效率极低的方法去检测。所以更加锻炼了我用计算机指令解决问题的能力。相当于一直绑着一堆沙袋练习跳远。同时间接地熟悉了微机原理,软件与硬件的关系,还有汇编语言。这种熟悉对于后来做C++开发高性能图形引擎,有极大帮助。别人碰到难复现bug束手无策,很多时候看汇编和寄存器情况就能大致猜出个1成到2成。

2)对问题难度极限的感受
我发现对一个程序员最大的阻碍,就是一种对解决问题极限难度的感受。决定了你最差的情况或者收入,这个很有可能和性格有关。当碰到一个问题,如果经过一段时间努力,你觉着太难了自己无法搞定,自然就放弃了。或者更深层的心理是:我已经挺牛逼的我技术也行,会得也多。这问题都什么玩意儿啊,要么就是老板给我的活有问题不是活人能做的,要么就压根是别人的问题。 这两种想法决定了你这个人混得最差的程度在哪里。

能力被动型

有些人天生就对问题跃跃欲试喜欢挑战和新。有些人一切以“我当前所掌握技术和能力为标准“来判断事情难度。管这类人叫“能力被动型员工“。被动型人水平也有高有低。较高水平的这类人很可能在之前某个人生阶段(比如聪明,大学被逼,年轻心态开放情况下)习得的知识和技术。但因为是被动型,非发展性人格,所以到了30之后会逐步走下坡路。

合格技术管理者和员工针对一个技术问题的沟通中,很容易发现“能力被动型员工”。这时候管理者心里会默默给你一个标签。以后只会选择你能力之内的工作给你。合理的使用你,只让你辛苦,不让你那么痛苦。由于你一直困在“当前这一秒我会的东西是最高难度“,也接触不到更多更新更难的事情。接触了也无心无力奋争解决,能力也不会提高。所以你和一个原地拉磨的驴子很像,体力耗光,也就卸磨杀驴了。

技术人都有发展自身能力和技术的倾向。主观上,如果你不是做一天和尚撞天钟,你肯定不认可自己是能力被动型。但有种学习的障碍,自己被自己知道的东西困住了。你认为的极限真的就是你自己的极限,和这个技术问题的极限吗?据我十几年的观察,多数情况下并不是。另外,工程实际是解决问题,不是用完美或者自认为满意的方法解决问题。这需要特别灵活的头脑。工程思维,和钻研理论与技术,用的是不同的思路。这种思维转换对很多技术人员有困难。久而久之,自己被自己耽误了。丧失了很多机会去突破自己的极限。

这种思维习惯不限于技术人员。一切靠一项技能吃饭的人,都会存在。如果这类人目光还短,只盯着眼前鸡毛蒜皮的小利,想不到5年到15年以后自己长期利益。那下场就更惨。这个和看工资待遇不矛盾。你既要看现在的待遇,也要看当前其他公司的更好待遇机会。更要去想5年或者15年以后的工资待遇。

技术管理

对技术人员,35岁之后合适的路之一,是技术管理。年轻人永远会进入这个行业。但软件行业是个工程行业。也就是需要一群人在一段时间共同完成一个任务的事情。所以一个稍大的项目,总需要一棵树一样的管理体系。每个节点都需要一个管理角色,当然这个角色本身也有可能是具体技术人员。

软件管理大致分两块,一块是软件开发与质量管理,一块是软件人才管理。办公室政治、拉踩竞争对手、拍好老板、争取资源、甩锅,这些也都是必备技能,不要忽视。至少做到不被绊倒。不去害人可以,但也不能被别人害了。 技术管理最大的好处是,组织需要你做出结果。软件按功能可以跑。 这个事比政治管理要单纯一些。

软件开发管理与软件质量管理,是技术管理人员很重要的能力。真感兴趣去搜索“软件工程“,”软件开发管理“,”软件质量管理“等关键字。就不多说了。你只要知道35岁这些关键字对你还房贷,养孩子很重要就是了。

人才管理就是组建团队,培养,分配工作,动态调整团队,调整每个人工作,以便让工程最大化顺利进行,问题最小化,预防问题发生。成本、工期与质量死亡三角控制等等。高科技人才管理自成一套体系。

管理也有科学理论。管理学之类,社会心理学,动机心理学等,记着多找书学习。别和那些野生管理者一样无知。最后就只能靠政治手腕,那种人一旦被斗下来,就成了傻逼。

劳心者治人,劳力者治于人;治于人者食人,治人者食于人。天下之通义也。你35岁被公司裁,或者你裁掉别人的时候,记着谢谢我。

对我技术生涯起到里程碑作用的读物 - 程序员生存救命书系列

我从事工作需要C/C++/C# ,OOA/OOD/OOP,软件架构等。后来技术管理也需要软件工程管理,质量管理,复杂度评估之类ISO/IEC25010/CMM 体系涉及到的东西。这是个人经验,不一定适合多数人,做个参考。在我那个时代(2010以前),万不得已不要看国内的书。最好是翻译不错的国外经典书籍(台湾也行)。2022的当下我不了解。

书籍非常关键。软件技术几本都靠自学。如果个人能力不足以自学精通,参加商业收费培训,更需要书籍指引。找到靠谱培训其实效率更高。问题就是很容易碰到二把刀教出三把刀。建议一定要参考教师自己过去从业经验,不要看广告吹嘘,只用看培训师亲自参与主力开发过的软件的规模大小,代码行数,软件的结果如何。

1、个人建议如果工作需要C/C++, 汇编语言一定要学,微机原理一定要学。我记着自己小学时候是拿着一本Z80指令集手册自学。后来家里买了学习机,换成APPLEII 说明书,后面也有很厚的指令集说明。通过学习芯片级的指令和功能,熟悉了微机原理,汇编等。使用更高级语言比如JAVA,C#,GO,PHP,JS的人,熟悉计算机底层指令运行原理,对于编程和调试也有好处。这个好处是,只要你写代码,脑子里都会一直有个宏观的电脑关键资源观念,就是内存和CPU都是有限的,最险恶的bug也都会最终体现到内存出错上。哪怕有GC,对object instance使用糊涂,也会导致那些极度难复现很偶发崩溃bug的出现。

2、合格coder必须掌握《数据结构与算法》。这就是搬砖的基础。

3、OOP程序员生存救命书系列,C++的是《C++ primer》《C++ 语言编程》(C++之父写的)太重要了。其他语言的也一定要看国外语言发明者或者相关红宝书。

4、性能程序员生存救命书系列。程序都牵扯性能, 《Effect C++》或者effect系列太重要了。另外所有领域,UI,逻辑,数据库,图形等等都牵扯速度和内存的优化。针对CPU和GPU以及内存,或者IO设备优化能力越强,薪水也会越高。当然那种代码可读性shit一样,没法与人合作的,单说。。。

5、特定平台编程救命系列。《操作系统》,《windows核心编程》,或者经典的其他OS《xxx操作系统核心编程》系列。。。开源系统上工作,最好能找OS代码解读类的图书,研究一下和自己工作相关的底层代码机理。

6、OOP码农和软工救命系列。到这里你已经是软件工程师了。。《设计模式》必看。因为大型复杂软件工程,是由一群智力不同的程序员合作开发。你想拿更多工资,就得能够搞定更大规模的软件,这就需要你管理和协同更多人工作,要协同就得让智力不同的人一起在统一思路下发挥自己能力。设计模式就是给普罗大众智力正常的OOP程序员们统一思路用的。这也是进阶架构师必经之路。大型软件可扩展性维护性等非功能性需求都指望这个了。过度OOD属于水平不行的,不是OOD和《设计模式》本身的问题。

7、lead programmer和tech leader救命系列。《软件架构设计》或者类似的国外经典书籍。当你负责的事大到一定程度,或者5个程序以上team干活栽坑时,这类书就能救命。也是你往更高架构师,tech director进阶必经之路。

8、tech manager救命系列。 《软件工程》 , ISO/IEC25010 ,CMM 规范。 如果哪个稍具规模公司技术管理者不熟悉ISO 25010 和CMM,建议CEO直接找他聊聊。或者开掉。在我而言不重视非功能需求,和软件成熟度的技术管理者做的产品,必然垃圾。他的技术团队必然垃圾。他的公司技术人才培训和发展,必然垃圾。重视了况且也可能垃圾,不重视就必然垃圾。至少tech manager要根据自己公司情况,把前面提到的相关信息,放入自己开发流程中。保障软件质量和团队能力发展。

9、架构师救命系列。 《软件需求分析》或者OOA相关书籍。 不具备基础软件需求分析能力的人,千万不要制定软件功能。甭管你是CEO还是CTO 。。。除了耽误时间人力和钱,什么作用也没有。需求分析也包括功能和非功能两大类,To c 和To b 软件是一样的,都需要细致周详的需求分析,哪怕是迭代式。

10、tech director救命系列。 找敏捷开发的书参考一下,我那个时代的极限编程之类不合时宜。但敏捷开发思路目前已经很成熟了。 野生tech director往往在工程方法论上都是用自己过去当码农的经验,胡拍脑袋。让自己训练有素必须加强敏捷软工方法论实践。

以上书籍不一定全,但也不需要齐全。需要注意的就是把自己所工作领域的三个层次都打扎实,35岁之后才不慌。 想从coder一路升到tech director那些是至少要掌握的。要求已经很低了,我在38岁之前的编程能力和精力,不觉着比25的差,虽然每个人的脑力不同。但从国外看,40多依然从事技术工作或者技术管理工作,是个很正常的事。尤其是技术管理,格外需要具备海量开发经验同时又有软工管理经验的人。


IT程序员进阶架构师的六项基本能力

架构师可以说是许多IT程序员的终极职业目标,这一岗位在技术团队中的发挥着总指挥和总架构的重要作用。一名合格的架构师需要具备多项基本能力,本节为大家总结了一下IT程序员进阶架构师需要的六项基本能力,分别是编程能力、调试能力、编译部署能力、性能优化能力、在线运维能力和架构设计能力。

1、编程能力
对IT程序员而言,编程是最基础的能力,也是一个必备技能。编程能力的本质是一个翻译能力,将业务需求翻译成机器能懂的语言。常见的编程范围:数据结构算法,比如:经典排序:插入排序、冒泡排序、快排(分划交换排序)、直接选择排序、堆排序、合并排序等;高级语言特性:JVM、类装载机制、多线程并发;设计模式:常见的单例、工厂等;UML建模:详细设计必备;网络与安全:网络协议、安全等;开源系列:spring、maven、redis、memcached、activeMQ等。

2、调试能力
调试能力是项目能否按时、高质量提交的关键。即使一个稍具复杂度的项目,大部分IT程序员也无法一次性准确无误的完成。大项目都是通过不断地调试进行优化和纠错的。所以,调试能力是IT程序员进阶架构师不可或缺的能力。

3、编译部署能力
编译并在线上部署运行程序是系统上线的最后一个环节。随着SOA架构的普及以及业务复杂度的增加,大部分系统只是一个完整业务的一个环节,因此,本地编译和运行并不能完全模拟系统在线运行。所以编译部署能力是一个架构师的必备技能。

4、性能优化能力
随着使用量的增加和业务复杂度的增加,大部分系统最终都会碰到性能问题。性能优化能力是一个综合能力。因为:影响系统性能的因素众多,包括:数据结构、操作系统、虚拟机、CPU、存储、网络等。为了对系统性能进行调优,架构师需要掌握所有相关的技术。精通性能优化意味着深刻理解可用性、可靠性、一致性、可维护性、可扩展性等的本质。性能调优集中在:JVM调优,线程池调优、SQL调优、索引优化、数据库垂直拆分等。

5、在线运维能力
残酷的现实是,无论程序多么完美,Bug永远存在。与此同时,职位越高、责任越大,很多架构师需要负责非常重要的在线系统。对于线上故障,如果不能提前预防以及快速解决,损失可能不堪设想,所以在线运维能力是优秀架构师的必备技能。

6、架构设计能力
我们说的架构设计能力分为两个方面,即业务和技术。优秀的架构师应该具备辨别真伪需求的能力,应该花时间去了解客户的真实业务场景,具备较强的业务抽象能力,洞悉客户的真实需求,这体现的是架构师的业务架构能力。与此同时,通过专业的技术手段实现用户的需求也是架构设计能力十分重要的一面。

IT程序员进阶架构师需要的基本能力就差不多总结到这里了。当然在成长的这条路上,没有人可以一蹴而就,都是通过长时间的学习、实践和思考,慢慢积累经验,从而完成完美的蜕变。希望大家都可以选择自己所热爱的东西,风雨兼程,最后一定能收获不一样的风景。

UML图的画法一览

软件开发是一个分阶段进行的过程,不同的开发阶段需要使用不同的模型图来描述业务场景和设计思路。在不同的阶段输出不同的设计文档也是必不可少的,例如,在需求分析阶段需要输出领域模型和业务模型,在架构阶段需要输出物理架构设计,在详细设计阶段需要输出数据库设计等。这样做可以更好地实践软件开发,并提高软件开发的实用性。

软件建模与设计过程可以分为三个阶段:需求分析、架构设计和详细设计。在这三个阶段中,大量使用符合 UML 规范的模型图,其中常用的有 7 种,包括类图、序列图、组件图、部署图、用例图、状态图和活动图。在需求分析阶段,使用用例图和领域模型图描述用户需求和业务场景。在架构设计阶段,使用组件图和部署图描述软件系统的组成部分和部署情况。在详细设计阶段,使用类图、序列图和状态图描述软件系统的实现细节。下面将探讨如何绘制这 7 种模型图,以及如何在不同阶段使用这些模型来生成相应的设计文档。

类图

类图是软件设计中使用最广泛的 UML 图形之一,用来描述类的特性以及类之间的静态关系。在一个类图中,每个类都由三个部分组成:类名、属性列表和方法列表。

除了描述类的基本特征,类图还用来表示类之间的关系,其中包括六种静态关系:
关联(Association):表示一个类对象与另一个类对象之间的关系,比如订单与客户之间的关系。
依赖(Dependency):表示一个类对另一个类的使用或调用,比如客户下订单时需要使用订单类。
组合(Composition):表示一种包含关系,表示一个类对象包含另一个类对象,比如一个订单包含多个商品。
聚合(Aggregation):也表示一种包含关系,但是聚合关系中包含的类对象可以被多个类共享,比如一个学校包含多个班级。
继承(Inheritance):表示一个类继承自另一个类,可以从父类中继承属性和方法,并且可以添加新的属性和方法。
泛化(Generalization):与继承关系相似,但泛化关系可以用来表示更抽象的关系,比如多个类都实现了一个接口。

通过绘制类图,我们可以清晰地描述一个软件系统中的类及其之间的关系,帮助开发人员更好地理解软件系统的结构和功能。

在UML工具中把相关的一组类及其关系用一张图画出来,就是类图。


如上图所示,描述的就是一个典型的责任链模式的实现类图。

类图主要是在 详细设计 阶段画,一旦类图设计完成,开发工程师可以根据类图来实现代码。只要类方法的逻辑不是太复杂,不同工程师实现的代码几乎是一样的,这有利于保证软件的规范和统一性。在实际应用中,通常不需要画出所有类的类图,只需要画出核心、代表性、技术难度较高的类图即可。


除了在详细设计阶段绘制类图外,还可以在需求分析阶段使用类图来表示关键领域模型对象。在这个阶段中,我们不要将注意力集中在属性或行为上,而应该专注于识别领域对象及其之间的关系。因此,可以使用简化的类图来描述,只需要绘制类的名称和它们之间的关系即可。

如上所示描述的是在需求分析阶段挖掘出SIM卡、运营商、手机、手机厂商等模型对象之间的关系。

序列图

类图之外,另一种常用的图形是序列图。

类图描述类之间的静态关系,而序列图用于描述参与者之间的动态调用关系。每个参与者都有一条垂直向下的生命线,该生命线用虚线表示。参与者之间的消息按照从上到下的顺序表示它们的调用顺序关系,这就是序列图这个词的来源。每个生命线都有一个激活条,它是图中的细长矩形条,只有在参与者活动时才是激活的。


通常使用序列图表示对象之间的交互,这些对象可以是类对象,也可以是更大的参与者,如组件、服务器、子系统等。总之,只要涉及到不同参与者之间的交互,都可以使用序列图,比如下面这张图就是业务分析阶段,系统建设后完成后的业务流程。


记住,在软件设计的不同阶段都可以使用序列图。

组件图

组件是比类更大粒度的设计元素,通常一个组件中包含多个类。组件图有时与包图的用途相似,通常用于描述物理组件,如JAR、DLL等。在实践中,我们更多地使用组件图进行模块设计。


组件图描述组件之间的静态关系,主要是依赖关系。如果想要描述组件之间的动态调用关系,可以使用组件序列图,以组件作为参与者,描述组件之间的消息调用关系。

由于组件的粒度较大,通常用于描述和设计软件的模块及其之间的关系。因此,在设计的早期阶段就需要画出组件图,一般用于架构设计阶段。

部署图

部署图描述的是软件系统最终的物理部署情况,包括需要部署的服务器数量、关键组件的部署位置等。它是软件系统最终呈现的物理蓝图,能够让客户、老板和工程师清晰地了解系统的最终运行状态,以及与现有系统和第三方服务器的关系。通过部署图,可以预估服务器和第三方软件的采购成本。

因此,部署图是整个软件设计模型中相当宏观的一种图,需要在设计早期就绘制。各方可以根据部署图讨论是否认可该方案,只有对部署图达成共识,才能继续后面的细节设计。部署图主要用于架构设计阶段,并且与组件图要彼此呼应。


用例图

用例图分为业务用例和系统用例,业务用例图主要体现在 业务分析阶段, 描述一个承建系统的组织对外提供的能力,系统用例体现在需求分析阶段描述系统对外提供的能力。


这张图中,左边是业务用例图,右边是系统用例图。虽然它们的画法相似,但它们本质上有很大的区别,具体可以查看我之前写的这篇文章。

图中的人形元素称为角色,角色可以是人也可以是其他系统。由于系统的功能可能很复杂,用例图可能仅包含其中的一小部分功能,这些功能被画在一个矩形框内,这个矩形框是用例边界。矩形框里面的椭圆表示单个功能,它们可以相互依赖或需要扩展。因为用例图中的功能描述相对简单,所以通常需要配以文字说明以形成需求文档。

状态图

状态图用来展现单个对象生命周期中的状态变迁。

在业务系统中,许多重要的领域对象都有相当复杂的状态变化,比如订单,它们可以有待付款、待审核、待发货、待收货、交易关闭和交易完成等各种状态。这些状态变化可以在用例图中用文本形式描述,并随着各个用户的不同操作而改变。但使用这种方法描述状态时,状态会分散到不同的地方,这样可能会导致开发错误以及产品经理在设计时的困惑。

采用UML状态图可以有效地解决这些问题,因为它可以在一张图表中展示对象的整个生命周期以及各个状态和变迁之间的关系。比如下面的图表展示了一个订单从创建到交易完成的状态变化。


状态图要在需求分析阶段画,描述状态变迁的逻辑关系,在详细设计阶段也要画,这个时候,状态要用枚举值表示,以指导具体的开发。

活动图

活动图常用于描述系统或业务流程中的动态行为。它可以清晰地展现从一个活动到另一个活动的控制流,描绘出系统或业务流程的逻辑和流程,让开发人员更好地了解整个系统的运作方式。

在活动图中,实心圆表示流程的开始,空心圆表示流程的结束,圆角矩形表示活动,菱形表示分支判断。这些符号的使用能够使活动图更加规范化和可读性,有助于提高系统开发的效率和质量。


此外,活动图引入了一个重要的概念——泳道。活动图可以根据活动的范围,将活动根据领域、系统和角色等划分到不同的泳道中,使流程边界更加清晰。

流程图也比较有普适性,可以在需求分析阶段描述业务流程,也可以在架构设计阶段描述子系统和组件的交互,还可以在详细设计阶段描述一个类方法内部的计算流程。

使用合适的 UML 模型构建一个设计文档

UML 模型图本身并不难掌握,但如何在正确的场合下用适当的 UML 模型表达设计意图,形成一套清晰且详细的软件模型,并在团队内外达成共识的设计文档则需要注意。根据软件设计不同阶段的需要,可以使用不同的模型图进行建模。

在需求分析阶段,我们可以使用用例图、活动图、时序图和简化的类图进行领域模型抽象和关系描述。

在架构设计阶段,通过组件图、组件时序图和部署图描述系统物理蓝图和模块关系。

在详细设计阶段,主要侧重于类图和类的时序图,而对于复杂的方法逻辑,可以使用方法的活动图进行描述。

小结

掌握类图、时序图、组件图、部署图、用例图、状态图、活动图这七种UML模型图,根据实际场景,在需求分析、架构设计和详细设计阶段选择并巧妙应用对应的模型图,有助于有效地进行软件建模和系统设计,成为一个掌控大局、指导技术团队的优秀架构师。

要注意模型图的规范和注释,遵循命名规范,对模型元素进行命名,注释模型元素的关系和属性等,简洁明了。此外,UML模型图只是设计文档的一部分,需要与其他文档相结合,如需求文档、设计文档、测试文档等,形成一个完整的设计文档,指导软件开发。

对于画UML的工具,有收费的专业软件设计工具像EA(Enterprise Architect) 、Astah和亿图,以及免费的在线工具比如draw.io,processon等,建议可以根据自身需要选择合适的工具,同时也建议从简单易用的工具入手。