当程序员写程序时在想什么和做什么
Contents
今天要从宏观角度讲一个程序员是如何写程序的故事,我们假设这个程序员是一个理想的程序员,并且是无所不能的,精力充沛的,因为这样可以减少涉及多人的合作和交流(即额外的成本),我们在本文中将避免讨论此类影响。当然,理想的程序员并不存在,世界上存在的是能力上有着极大差距的个体,很多项目也需要多个程序员或者细分的其他角色来合作开发。
一、需求,市场,预算
现在我们要写一个程序,这个程序需要去解决一个自己的或者别人的问题,而且目前这个问题,一定还是很模糊和笼统,比如,”做一个淘宝“。 正如一万个人心中有一万个汉姆雷特,一万个人心中也有一万个“淘宝”。市场上常常出现两极分化的极端,比如需求方可能会说“做一个简单版的淘宝app,一千的预算”,cto们则会说,这个得上分布式大数据AI大模型,几亿起步。 理想情况下,当然是互相坦诚的交流最好,因为将一个现实世界中的需求转化为程序,必定需要对其的详细理解,以及将其转化成抽象程序的两种能力的和谐共存,即所谓的”领域知识“和”专业能力“。然而现实当中,需求方和实现方都不想自己显得“无知且愚蠢”,因为这涉及到互相之间对能力的评估,进而涉及到对经济上支出和收入的影响。 没有人愿意承认自己是一个“傻瓜”,自己的需求没有“高成长性的市场”,需求沟通不畅,市场定位不清,可想而知,关于时间和资金的预算,自然就难以清晰了。 这里已经做了很多简化,如果再涉及到权力机构,市场竞争,贪腐,那问题将更为复杂。 于是这部分工作从”无所不能的程序员“的工作中划分了出去,给予了销售,售前,市场,产品等部门和角色。当然这些角色很多在传统行业或者其他行业中也存在,互联网行业有什么特殊的呢?
二、技术选型、架构、最简可行产品
假设我们有着极佳的运气,避免了一切人性在沟通和交流上的弱点,梳理清楚了需求,至少梳理清楚了一部分需求。我们可以开始着手写代码了吗?不,还不能。 我们已经处于二十一世纪的第三个十年,不是二十世纪的七八十年代,市场上充斥着各种”组件“,如开源软件,框架,原型,工具,没有人会从头开始造轮子,那样有太高的成本。现代社会没有人会对用多功能电压锅煮面条觉得奇怪,所以你在你的产品中引用第三方”组件“,并且仅仅使用它的一部分功能也是自然而然的一件事情。 问题在于选择,而且选择太多。如果把需求划分成不同的小需求,那么不同的第三方”组件“可能会满足多个不同的小需求的组合,同一个小需求也可能有多个第三方组件实现。有些时候,第三方组件不能完全满足你的需求,需要一些修改,有些时候,你会觉得第三方组件引入的成本太高,决定自己写代码。 上面的部分只是面对”需求“,对于程序员来说,他还需要面对”硬件“,包括CPU,网络,硬盘存储,所有的第三方“组件”,以及他自己编写的代码,对于“硬件”能力的发挥都有着不同的使用难度和性能差距。 这些就是架构和技术选型的工作,程序员不仅仅需要面临需求的压力,硬件的限制,他还要受到时间预算和资金预算的压力。 “无所不能”的程序员也不可能理解市面上所有第三方“组件”的所有功能点,以及对硬件的特性,于是分化出了更为细致的岗位:前端工程师,后端工程师,数据工程师,运维工程师,等等等等。我们不叫这些角色“程序员”而称呼他们为“工程师”,理想上,他们确实应该对自己擅长的领域“精益求精”。 如果考虑到“最简可行产品”,问题将更为复杂。最简可行产品(MVP)是只包含核心功能可以用来给客户体验和反馈的产品,可能很快就会被抛弃,也可能会有很快的增长压力,这给选型和架构带来了更加复杂的外部条件。 回答上一章节结尾的问题,这或许就是互联网行业的特殊所在,程序化的虚拟世界能够快速迭代和变化,任何角色和工作,即使从“无所不能的程序员”身上分离出去了,也仍然需要和程序员有海量和即时的沟通需求。
三、组件
如前文所言,现代的程序极少从零开始编写,而是会继承多个第三方组件进行裁剪,组合,并编写新的代码像”胶水“一样进行粘结。在安装这些第三方组件时,很少有人会通读这些第三方组件的代码,而是通过说明文档,配置文件,库函数调用,API调用等来使用。而这里同样混杂着两种细节:功能需求的细节和硬件使用的细节。 第三方组件也同是由程序员来编写,因而这里同样会出现各种问题,如文档匮乏导致无法完全理解需求和对硬件的影响,bug或者崩溃,无法完全满足需求的二次开发等等。 正如上一章所言,”无所不能的程序员“拆分出了不同的角色来解决这些问题,对于成熟的第三方组件,有”数据库管理员’,“运维工程师”,“大数据工程师”,“中间件工程师“等。并不是说这些程序员不开发新的代码,这里的含义是,他们的工作和技能的中心,大多会围绕在少数第三方组件的使用和二次开发上。
四、工具
假设我们再次幸运的清楚了最简可行产品的所需功能,以及要使用的第三方组件,现在我们终于可以开始写代码了。 各种开发工具比如编辑器,IDE,文档程序等,是程序员在写程序时首先面对的事物。这些工具在外行人的角度来看充满了魔法和神秘,毕竟对于很多人来说,打开电脑上网或者操作一些桌面软件就是一件有一定复杂度的工作了,更多的人已经习惯于手机上的几个固定的APP。 即使从内行人的角度讲,这些工具同样充满了挑战性,复杂的交互,难以理解的配置,“尽量少碰“,”能跑就好“,这是绝大部分程序员的共识。那么工具里隐藏了什么? 以集成开发环境IDE为例,其并不仅仅是一个”文本编辑器“,否则就可以用一个记事本或者写字板工具代替了,这里面包含了大量编程语言的特性以及常见周边工具的集成。也即是说,当我们一开始写下第一段代码时,想要用好常见的工具,便要对所使用的语言,有着相当程度的了解。当然很多工具的默认配置已经足够使用,但仍然保留着一种风险,即当工具因为任何原因出问题时,如何让使用者修正这个问题。 这并不是一个新手友好的工作,尤其在这一个当越来越多的人在使用windows时,对“文件树”都难以理解的时代。 无论自我的规范,还是团队的规范,都应该从这一刻开始,一个简单的收益便是确定缩进的规范,避免后期多人代码合并时的“空格”冲突。但也许是收益过小,或者是对于管理者来讲亮点不足,这种规范在小公司很难听到自顶向下的声音,反而多为一线员工互相抱怨和内耗的共识。 优秀的程序员会寻找各种好用的工具,并将其调整成适合自己工作的方式,甚至自己开发工具给自己或者身边的人使用,在开源软件里,我们可以看到很多类似的优秀例子。
五、语言
现在我们终于要使用编程语言写下第一行代码了。等等,要用什么语言来实现呢?这里又取决多个因素:
- 运行的硬件和操作系统:ios或者android手机?linux服务器还是windows桌面?或者是嵌入式系统?
- 语言更贴近硬件还是开发人员:这个时代没有多少人去写汇编语言了,然而c++和python还是在运行效率和开发友好度上有很大的区别 这些问题多数应该在前文的需求和选型中解决掉了,在这里对程序员的影响主要是编程语言的语法细节,以及对硬件的抽象。 在这一阶段,我们常常听到的一些词是:1. 算法 2.数据结构 3.并发及并行 4.进程及线程 5.内存模型 6.缓存 7.中断 8.同步等, 当然还有面向对象编程,函数式编程,设计模式,重构,还有许多。这里的工作,包含了对业务的极致抽象,以及随语言而变的、对硬件不同层次的操控。 第三方组件终其本源而言,工作重点也是在这一部分,对工作的一丝不苟,对硬件细节的极致掌控,优雅规范的设计,天马行空的想象力,全部在这一部分体现。当然,所谓的”屎山代码“也会在这里露出原形。 不同的编程语言对上述的关键词有不同的实现方式,于是这里又分化出了”c++程序员“,”java程序员“,”python程序员“等等。 但是编程并不只是对语法的了解,更是对上述关键词本质的理解,以及前述章节内容的熟悉。通过不同语法的语言来区分程序员的种类,大致是对这个行业的常见外行理解之一。
六、测试及交付
没人可以保证自己的代码可以不经一次修改的完全正常工作,另外,代码实现的功能是否满足了需求,也需要仔细验证比对。 如果说前述章节描述的工作,我们一直强调的是需求和硬件的匹配实现,那么测试似乎就可以理解成为对这种匹配的一致性的检测,从最初的需求开始,各种第三方组件,架构,到代码,硬件,整个系统是否能够按照预期工作;检测功能,性能,安全性,检测边界条件下是否稳定运行,最后再交付上线给最终用户。日志和监控是这一阶段的两大重要关键词。 理想情况下,程序员应该将这部分工作融入到日常中,他每完成一段代码,一个函数,一个功能,接入一个第三方组件,都应该不断测试程序的工作是否符合预期。 但是即使对于”无所不能的程序员”,这部分工作也过于繁琐了,所以很多时候在完成部分测试后,还是会将另外一部分测试工作交给新的角色,比如“测试工程师”,无论他们是在做手动的功能测试还是时兴的自动化测试,还有“交付工程师”,“售后工程师”等等。 这一章节似乎最短,但是如果真要细化起来,便又成了整篇文章的复述,每一个表面的问题的展现,都可能需要层层拆解:需求是否自洽,第三方组件的使用问题,代码的逻辑问题,硬件的影响比如并发编程bug。 “行百里者半九十”,当我们构建一个完善的测试和交付系统的时候,需要的工作量和和涉及到的技术细节,并不比实现原业务系统简单多少,某种角度上讲,测试工程师或许才是最熟悉所有需求和技术的角色,虽然他并不需要负责不断的设计迭代和最终实现。质量保障工程师(QA)才是最为准确的称呼。
七、AI能替代程序员吗
如果程序员的工作仅仅是同硬件打交道,或者仅仅同代码打交道,那么AI可以完成相当多的人力工作,如本文的第五部分,代码即使不能一次性完成,总可以通过人工调整来纠正细节上的错误。 问题和困难在于其他部分,如何理解和描述现实的需求,如何测试程序和客观相符,这些目前并不是AI可以完成的,仍然需要”人工“作为媒介同外部世界进行交互。给AI一个”开发一个淘宝“的提示词,这有太多的可能,无助于产生符合客观需求的程序。也许有一天AI能够自身观察和干涉物理世界,但至少在这一天到来之前,挖掘需求并为AI描述清楚,并且熟悉技术细节给予AI反馈的程序员,仍然不可替代。