”如果你思虑不周,你也许会认为编程只是一行一行把代码语句敲进电脑里。“——Ward Cunningham 在《程序员修炼之道:从小工到专家》中的序言提到。
软件开发包含很多需要深入思考的内容,诸如设计、解决问题、找出最佳算法,学习新语言,重构混乱的代码,使其变得整洁而优雅等等。
当你尝试去做一件你从没做甚至从来没有人做过的事;或者你以前做过,但毫无疑问不想再犯类似的错误,而需要去思考一个更好的方法;或者你尝试去理解其他人写的代码以便修改;或者你正在查找一个讨厌的BUG。所有这些都会占用大量的时间,但最终并不会产生很多代码。
同时软件开发中也有许多需要大量打字而不需要过多思考的工作。比如当你很清楚需要做什么并且如何做时,但是在工作完成之前,你需要编写大量的代码, 因为你之前做过类似的东西,所以仅仅需要再做一遍,用另一种脚本,适应另一种屏幕,另一种报告,另一种除了思考之外的所有东西;或者工作中大部分需要思考 的工作已经有人为你做好了,他给你提供了程序线框图,精确向你描述这个程序看起来的样子,给人的感觉以及数据的流动,或者提供了详细的API说明,所以, 你要做的事仅仅是把这些思考的结果敲进屏幕同时确保不要犯太多错误。
调试程序是思考型工作(Debugging is thinking)。而修复BUG、使其通过测试、发布主要是输入型工作。早期的设计和开发,决定使用的技术并设计框架,是艰难的思考型工作,而基于此开 发三个、四个或100个的适应屏幕或报告的程序是输入型工作。用户体验和原型设计是思考型的工作,而将其实现(包括CRUD、适应不同屏幕的配置)却是输 入型工作。找到一个酷的移动应用点子是思考型工作,而实现它却是输入型工作。解决一般的业务问题需要大量的编码,而通过软件优化业务流程去需要大量艰难的 思考。
所以,思考型工作的人和输入型工作的人做着不同的工作,并且需要用不同的方式管理。
有时候编程就是在打字输入
”我们首先是打字员,然后才是程序员。“——Jeff Atwood, Programming Horror
许多业务程序本质上是很肤浅的。大量的数据库表和文件充斥着大量的元素和数据,大量的增删改查页面、报表相互之间有许多的相似之处;大量的集成工作 把不同属性的不同点映射统一,从而使其满足约束并在操作上独立对待。功能需求上冗长的列表,通过一大堆的问题确保每个人都理解需求,许多细节描述用来备忘 和追踪。银行、保险、政府、会记、财务报表和账单、库存管理和ERP系统、CRM系统,企业内部应用、簿记系统、记录系统等等都是如此。许多在线门户和商 店也一样。一些维护型工作,如平台升级、系统集成和移植、税收变化等也是如此。
你是在建造一幢房子、一座桥、一个百货商场,或是改造其中之一。大项目经常不断滋生各种问题,通常要花费大量时间去解决。很多输入型工作需要做,但是其中有一部分之前已经做过很多次了,那些工作涉及类似的问题,所以你可以应用熟悉的模式、被证明可靠的工具和工作方法。
“我昨天看了你电脑程序的源代码,它看起来很简单;只是打了很多字,其中一半还拼写错误。还有,别再让我抱怨你那过渡使用的冒号了。” —— 《The Pointy Haired Boss sees some actual code》
一旦设计确定,绝大部分工作都被充分理解并考虑了所有的细节,剩下的就是管理和协调程序员去把这是代码敲出来。这是一种经典的项目管理流程:预算、计划、跟踪成本和调整、管理计划。这是关于逻辑、规模、一致性和效率的问题,确保工作在正确的轨道上运行。
思考!思考!思考!
其他的问题,比如设计一个游戏引擎、交易算法、物流或在线风险管理系统、优化一个实时控制系统,这些工作需要的思考都大于输入编码。这些系统有着高 标准、非技术性需求(可扩展性、实时性能、可靠性、数据完整性和正确性)和复杂的逻辑,但是他们集中在解决一系列紧密结合的问题。只有很少一部分聪明的程 序员可以思考那些问题并实现。当然,编码工作仍然需要去做,特别是“外围”部分,框架、管道、布线方式等,但是核心的部分通常只有非常少量的代码,尤其是 在抛弃失败的试验和原型之后。
这就是软件的奥秘所在,有版权或专利的算法和设计的洞察力是一个成功系统的核心。这种工作需要花费大量的时间去研究、需要无数次的设计原型、需要解决问题的能力,要么需要过硬的技术,要么需要深刻的领域知识,又或者要求二者兼备。
编码输入和思考是不同种类的工作
工作的性质以编码为主,还是以思考为主,影响着你的团队需要的人员数量和类型。这会改变人们之间如何合作,以及你如何取管理团队。编码可以被外包,但思考不行。你需要认识到哪些问题可以通过编码解决,而哪些不行,以及什么时候思考型工作转变为编码输入型工作。
思考型工作可以也应该交给一个小而精的专家团队,或者干脆托付给一个天才。在思考设计或思考复杂问题、反复试验的阶段,你不需要太多的人。做这种工 作的人需要完全沉浸其中,在这段时间里,他们会开展探索性研究,也可能会犯错误,他们会学习,在遇到困难时,也许仅仅会盯着屏幕发呆(其实是在思考啦 ^_^)。
这个阶段极其重要,因为在此所犯的错误通常都是致命的(终结项目或职业生涯级别的错误)。比如选择了错误的技术平台;假设了错误的实时系统的可容忍延迟;花费大量的时间去寻找(或者根本找不到)高可靠性的方案;挑选了错误的人员或者尝试去解决错误的问题;使项目失去了节奏。
管理此类工作需要寻找最优秀的人才,确保他们有正确的信息和工具,让他们专注,同时要观察外界的风险,以确保他们不被打扰。
思考型的工作是不可预知的。不存在“复制粘贴”的方法,因为你根本不知道从哪“复制和粘贴”。你不可能估计此类工作,因为你根本不知道有多少事务是你所不知道的。但是你可以设置一个时间限制,尝试寻找规定时间内的最佳方案。
编码输入型工作是可预知的。你可以同时也不得不去估计这类工作。诀窍在于把所有需要编码的工作的列出来,并为工作中所有可能遇到的错误和变化做出估 计。它们通常会随着项目的进行而快速增加,诸如程序员的粗心大意、错误理解了需求、遗漏了测试、简单的“复制粘贴”,这些都会导致现在和将来的成本增加。
编码输入是一种工人式的工作。虽然一些高级开发者在他们厌烦前可以媲美一个大团队的工作,但是你不需要专家,那些理解所用语言和工具的基本原则、细 心并且愿意服从指示、耐心的人都可以胜任此类工作。管理一群“打字员”需要不同的方式和技巧:你需要尝试变成一个政客、一个外交家、一个后勤人员、一个标 准制定者、一个管理员、一个经济学家的角色。你是在管理项目和人员的风险,而非技术。
一段时间后,一旦大部分“我们不确定我们需要且如何去做”的艰难工作被解决了、一旦未知的事务被逐渐掌握,思考型工作就转变为了输入型工作,这时候就需要去填补细节并使流程跑通。
当系统的用户增加,不得不去处理更多的接口、地点、本地化、电子邮件、摘要、支持和承诺时,你就需要开展更多的输入型工作。系统保持增长,但是大部分的问题都是熟悉且可解决的。有大量的代码可供查找、学习和复制。你需要的是能够从中挑选所需和打字快的程序员。
思考和编码/输入
思考和编码都是软件开发的重要组成部分。
在《编程不仅仅是打字》一文中。Brendan Enrick解释了结对编程有用的原因:这可以让两个程序员同时各自专注在思考和编码两个方面。
”两个人都在思考,但思考的内容不同。一个开发者拥有键盘,并且沉浸其中(这种开发者需要一定的打字速度),他依照当前的代码逻辑进行编码而不是整个应用的结构。一段时间后,他编码的速度就会提高。
在结对编程中不实际编码的人把所有的时间都专注在思考上。他的脑子中具有编码者工作的清晰流程,但并不关心实际编程语言的语法,实际的编码者才需要关心语法。这种在编码者身后坐着的人,更像是一位向导,他必须确保工作进展在正确的道路上,并使用最有效的方式去实现它。“
成为一位优秀的开发者比单纯的编码输入更出色,而成为一位得力的编码输入者也比简单的敲击键盘更优秀。这意味你必须有很好的基础:掌握足够的编程语 言特性,知道用什么工具以及如何使用,要会读代码,当然也要知道如何写代码(同时要写得快);学会控制你的工具、知道使用哪种编码更快,这样你就更加灵 活,这些都是接替一个开发者所必须的。最后,不要低估编码输入的重要性,也不要让那些本该是输入型的工作变成思考型的工作。
原文链接:http://swreflections.blogspot.com/2013/10/programming-thinking-or-typing-thinking.html