高效程序员的好习惯

目录

1. 学习如何阅读别人的代码

2. 对坏项目的感觉

3. 避免不必要的会议

4. 使用Git

5. 编写简单可维护的代码

6. 学会说不,分清主次

7. 场景化思维

 40个好习惯

更多好习惯

拥抱unix哲学

选一个样板,follow之

写代码,而不是调代码

聪明地调试

使用标记语言来写文档,而非word/power point

一切皆项目

心态开放,勇于尝试


软件工程师花费大量时间通过练习leet code问题和完善简历来获得更好的面试通过可能。一旦他们最终被谷歌、亚马逊或其他公司录用,他们可能会发现:过去用来得到这份工作的技能与他们日常工作中需要的技能并不匹配。

我们的团队受到 TechLead 创建的高效程序员七项技能的启发。我们想提供我们自己对这个话题的看法。以下是我们总结的高效程序员的七项技能。


1. 学习如何阅读别人的代码

除了你,每个人写的代码都是垃圾?实际上,能够在别人的代码之上继续工作是一项有多重好处的伟大技能。

不管以前工程师的代码是多么混乱或者考虑不周,您仍然需要能够扩展它。毕竟,这是你的工作。同时,这个“以前的工程师”也可能是一年前的你。

这项技能在两个方面对你有益。第一,能够阅读他人的代码是一个了解什么是糟糕设计的好机会。当你浏览别人的代码时,你会知道什么是有效的,什么是无效的。更重要的是,您可以了解什么类型的代码对于其他工程师来说是容易扩展的,以及什么类型的代码难以扩展。

你需要确保在阅读他人代码时尽可能多地找出问题所在。这样,其他的工程师就会知道你是一个多么优秀的工程师。确保您提出了关于可维护代码和良好注释的重要性观点。这进一步显示了你在编程领域的优势。

您的代码应该设计得非常好,不需要任何文档。事实上,如果你是一个好的程序员,你不需要任何文档来说明你的任何代码。这只是浪费时间,更需要你花时间的是编码和开会。

能够阅读别人乱七八糟的代码的话,也使得在需要更新的时候变得容易。这有时意味着更新您缺乏经验的代码。例如,我们曾经将一个脚本从 Powershell 更新到 Python 再到 Perl。我们在Perl方面的经验有限,但我们仍然有足够的背景知识来弄清楚这段脚本到底做了什么,并做出必要的改变。

这一切都来自于对所有代码的良好理解以及能够阅读以往的代码。阅读别人的代码会让你变得有价值,因为这项技能甚至可以让你接手那些让别人难堪的过度工程化的系统。


2. 对坏项目的感觉

有许多技能需要花时间去学习。我们认为值得了解的技能之一是理解什么项目不值得做,什么项目显然是行尸走肉。

大公司总是有非常非常多的项目在进行(老板自己都不知道有多少),其中有些项目可能永远都不会完成,即时完成了,可能对公司也没有什么有利的影响。有些可能本身就没有任何商业意义(至少对你来说不是) ,还有一些项目可能存在管理不善的问题。这并不是说当你不认可一个项目时,你应该立即拒绝这个项目。最嗨还是看看项目干系人是如何看待这个项目的,如果他们自己都不能正确地解释他们对这个项目的最终成果会怎么样的,那么可能这个项目就不值得做。

此外,有些项目可能过于专注于技术而不是解决方案,以至于从一开始就很清楚不会有太多的影响。这个技能需要你在知道一个糟糕的项目到底是什么之前做很多糟糕的项目。所以,不要过早地花费太多时间试图辨别每个项目。

在你职业生涯的某个时刻,你会拥有良好的直觉与意识。


3. 避免不必要的会议

无论您是软件工程师还是数据科学家,会议都是必不可少的,因为您需要能够与项目经理、最终用户和客户达成共识。然而,也有一种倾向,会议会突然接管你的整个时间表。这就是为什么学会如何避免不必要的会议是很重要的。

也许一个更好的词是管理,而不是避免。这里的目标是确保你把时间花在能够推动决策和帮助你的团队前进的会议上。

最常见的方法就是每天抽出两个小时的时间,这是一个持续不断的会议。通常,大多数人会在他们认为有益的时候定期召开会议。他们会利用这段时间来赶上他们的开发工作。

另一个避免开会以便完成工作的方法是在别人之前出现。就我个人而言,我们喜欢早到,因为一般来说,办公室比较安静。大多数早到的人和你一样,只是想把工作做完,这样就不会有人打扰你了。

这对个人贡献者来说很重要,因为我们的工作需要我们集中注意力的时间,而且我们不会和其他人交谈。 是的,有时候你可能需要解决问题,你可能想和其他人一起工作。但是一旦你解决了阻塞问题,你只需要编码。它是关于进入那个区域,在那里你不断地在你的头脑中有许多关于你正在做的工作的复杂的想法。 如果你总是停下来,很难从中断的地方重新开始。


4. 使用Git

一些计算机专业的学生在他们出道的那天就开始使用 Git 了。他们不需要专业人士指导就可以理解每一个命令和参数。其他人在他们的第一份工作中第一次体验到 GitHub。 对他们来说,Github 是一个地狱般的地方,充斥着混乱的命令和进程。他们永远都不是100%的确定自己在做什么(备忘录之所以流行是有原因的)。

无论您的公司使用什么仓库系统,如果您正确使用它,该系统都是有用的,如果使用不当,则是一个障碍。一个简单的commit或push就可以让你花上几个小时来理清一些由多个分支合并组成的大杂烩。此外,如果您经常忘记使用仓库的最新版本,那么您还将处理不那么好玩的合并冲突。

如果您需要一个 Git 命令备忘单,那么就做吧。只要能让你的生活更简单。


5. 编写简单可维护的代码

年轻的工程师可能会有一种倾向,那就是试图将他们所知道的一切都实现到一个解决方案中。有一种愿望,那就是把你对面向对象程序设计、数据结构、设计模式和新技术的理解用到你编写的每一个代码中。然后,你就很有可能创建了一个不必要的复杂性,因为它很容易过度依附于您过去使用过的解决方案或设计模式。

在复杂的设计概念和简单的代码之间取得平衡。设计模式和面向对象设计应该尽可能的去简化宏观计划中的代码。进程越是被抽象、封装和黑盒化,就越难以调试和维护。


6. 学会说不,分清主次

这一条适用于团队中的任何角色,不管你是财务分析师还是软件工程师。但对于技术角色似乎每个人都更需要学会这一条。如果您是一名数据工程师,您可能会被要求做更多类似开发方向的事情。一些团队需要数据提取,其他团队需要仪表盘,其他团队又需要新的数据分析对接。

区分事情的优先顺序和说不,是两种不同的技能,但它们紧密地交织在一起。优先级区分意味着你只花时间在对公司有很大影响的事情上。然而,说不有时只是意味着回避应该由其他团队来处理的工作。对于所有角色而言,它们经常同时出现。

这可能是一个很难获得的技能,因为你总是希望用自己的方式去满足每一个请求。尤其是你刚从大学毕业。你想避免让任何人失望,而且你总是能得到大量的工作。但是,在大公司里总是有无穷无尽的工作量,所以一定要抓住关键:只承担能做的事情。

有很多技能在面试中是没有办法测试和验证的,甚至在大学里都没有教过。通常情况下,这更多的是环境的限制,而不是缺乏让学生暴露在真实环境中发展成长的愿望。


7. 场景化思维

有一种技能在面试中很难测试,在大学学习时也很难复制,那就是思考最终用户可能会如何错误地使用你的软件。我们通常将其称为场景化操作思维。

由于大部分编程都是维护性的,因此它通常意味着更改与其他代码高度耦合的代码。即使是简单的更改也需要跟踪对象、方法和 API的每一个可能存在引用的地方。否则,很容易意外地打破你没有意识到的模块连接。即使您只是更改数据库中的数据类型。

它还包括在进入开发之前通过边缘案例和整体化的高级设计进行思考。

对于开发新模块或者微服务的场景就更加复杂,花时间去考虑所构建的操作场景非常重要。想想未来的用户可能需要如何使用您的新模块,他们可能会如何不正确地使用它,可能需要什么参数,以及未来的程序员是否会以不同的方式需要您的代码。

简单的编码和编程只是问题的一部分。创建一个在你的电脑上运行良好的软件是很容易的。但是部署代码可能出错的方式就会有很多。一旦进入生产环境,就很难说代码将如何使用,以及哪些其他代码将附加到原始代码中。五年后,未来的程序员可能会对你的代码局限性感到沮丧。

    本文首发:http://blog.didispace.com/7-habits-of-highly-effective-programmers/

    欢迎关注我的公众号:程序猿DD,获得独家整理的学习资源和日常干货推送。

    如果您对我的专题内容感兴趣,也可以关注我的博客:didispace.com
————————————————
版权声明:本文为CSDN博主「程序猿DD」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/dyc87112/article/details/103885236

 

转载自 http://blog.chinaunix.net/uid-25838286-id-3264992.html,由作者 wenhuihhwh 原创。

 40个好习惯


每一个好的习惯,开头都会相应有一个唱反调的句子哦。
 
1 做事
“出了问题,第一重要的是确定元凶,找到那个人!一旦证实了是他的错误,就可以保证这样的问题永远也不会再发生了。”
指责不会修复bug, 把矛头对准问题的解决办法, 而不是人。这是真正有用处的正面效应。
也许你不相信,但确实有些人常常不把解决问题放在最高优先级上。也许你也没有。先自我反省一下,当有问题出现时,“第一”反应究竟是什么?
一个重大的错误应该被当作是一次学习而不是指责他人的机会。
团队成员们在一起工作,应互相帮助,而不是互相指责。
如果你没有犯过任何错误,就说明你可能没有努力去工作。
 
2 欲诉则不达
“你不需要真正地理解那块代码,它只要能够工作就可以了。哦,它需要一个小小的调整。只要在结果中再加上几行代码,它就可以工作了。干吧!就把那几行代码加进去,它应该可以工作。”
拙劣的代码工人会这样不假思索地改完代码,然后快速转向下一个问题;而 优秀的程序员会挖掘更深一层,尽力去理解为什么这里需要加1,更重要的是,他会想明白 会产生什么其他影响。
千里之堤,溃于蚁穴,大灾难是逐步演化而来的。一次又一次的快速修复,每一次都不 探究问题的根源,久而久之就形成了一个危险的沼泽地,最终会吞噬整个项目的生命。
如果有一位团队成员宣布,有一块代码其他人都很难看懂,这就意味着任何人(包括原作者)都很难维护它。请让它变得简单些。
 
3 对事不对人
“当L先生在做一个新方案介绍时,下面有人会说‘这样设计很蠢!都没有考虑线程安全!’(这也暗示着L先生很蠢)。”
事实上,最适合并且最有效的表达方式应该是“谢谢,L先生。但是我想知道,如果两个用户同时登录会发生什么情况?”
尽力贡献自己的好想法,如果你的想法没有被采纳也无需生气;不要因为只是想体现自己的想法而对拟定的好思路画蛇添足。
 
4 排除万难,奋勇前进
“老鼠们打算在猫的脖子上系一个铃铛,这样猫巡逻靠近时,就能预先得到警报。每只老鼠都点头,认为这是一个绝妙的想法。这时一个年老的老鼠站出来说道’那么,谁愿意挺身而出去系铃铛呢?’毫无疑问,没有一只老鼠站出来。当然,这个绝妙的计划也就这样泡汤了。”
有时,绝妙的计划会因为勇气不足而最终失败。尽管前方很危险,但你 必须有勇气向前冲锋,做你认为对的事情。
当你勇敢地站出来时,如果受到了缺乏背景知识的抉择者的抵制,你需要 用他们能够听懂的话语表达。“更清晰的代码”是无法打动生意人的。节约资金、获得更好的投资回报,避免诉讼以及增加用户利益,会让 论点更有说服力。
 
5 跟踪变化
“软件技术的变化如此之快,势不可挡,这是它的本性。继续用你熟悉的语言做你的老本行吧,你不可能跟上技术变化的脚步。”
如果只是掌握了工作中需要的技术并不够。那样的工作也许几年之后就不再有了—它会被外包或者会过时,那么你就将会出局。
迭代和增量式的学习;了解最新行情;参加本地的用户组活动;参加研讨会议;如饥似渴地阅读。
 
6 对团队投资
“不要和别人分享你的知识—自己留着。你是因为这些知识才成为团队中的佼佼者,只要自己聪明就可以了,不用管其他失败者。”
团队中的开发者们各有不同的能力、经验和技术。 每个人都各有所长。不同才能和背景的人混在一起,是一个非常理想的学习环境。
一个学习型的团队才是较好的团队。
每周,要求团队中的一个人主持讲座。他会给大家介绍一些概念,演示工具,或者做团队感兴趣的任何一件事。你可以挑一本书,给大家说说其中一些特别内容、项目或者实践,无论什么主题都可以。
 
7 懂得丢弃
“那就是你一贯的工作方法,并且是有原因的。这个方法也很好地为你所用。开始你就掌握了这个方法,很明显它是最好的方法。真的,从那以后就不要再改变了。”
打破旧习惯很难,更难的是自己还没有意识到这个问题。丢弃的第一步,就是要意识到你还在使用过时的方法,这也是最难的部分。另一个难点就是要做到真正的丢弃旧习惯。 毕竟,汽车要比马车车厢强多了。
不是完全忘记旧的习惯,而是只 在使用适当的技术时才使用它。
 
8 打破砂锅问到底
“接受别人给你的解释,别人告诉你问题出在了什么地方,你就去看什么地方。不需要再浪费时间去追根究底”
要不停的问“为什么”。不能只满足于别人告诉你的表面现象,要 不停的提问直到你明白问题的根源。
问“为什么”,但是 要问到点子上。
当你问“为什么”的时候,也许你会被反问:“为什么你问这个问题?”。在提问之前, 想好你提问的理由,这会有助于你问出恰当的问题。
 
9 把握开发节奏
“我们很长时间没有进行代码复审,所以这周会复审所有的代码。”
在许多不成功的项目中,基本上都是随意安排工作计划,没有任何规律。那么样的随机安排很难处理。你根本不知道明天将会发生什么。
但是, 敏捷项目会有一个节奏和循环,让开发变得更加轻松。Scrum约定了 30天之内不应该发生需求变化,这样可以确保团队有一个良性的开发节奏。(Scrum是一种迭代式增量软件开发过程,通常用于敏捷软件开发。包括了一系列实践和预定义角色的过程骨架。)
站立会议最好每天在固定的时间和地点举行,比如说上午10点左右。要养成这样的习惯,在那时就准备好一切参加站立会议。
 
10 让客户做决定
“开发者兼具创新和智慧,最了解应用程序。因此,所有关键决定都应该由开发者定夺。每次业务人员介入的时候,都会弄得一团糟,他们无法理解我们做事的逻辑。”
在设计方面, 做决定的时候必须有开发者参与。可是,在一个项目中,他们不应该做所有的决定,特别是业务方面的决定。
记录客户做出的决定,并注明原因。好记性不如烂笔头。
 
11 让设计指导而不是操纵开发
“设计文档应该尽可能详细,这样,低级的代码工人只要敲入代码就可以了。编写代码的时候,无论你发现什么,绝不能偏离了设计文档。”
设计满足实现即可,不必过于详细。
即使之前已经提交了设计文档,也还会有一些意料之外的情况出现。时刻谨记, 此阶段提出的设计只是基于你目前对需求的理解而已。一旦开始了编码,一切都会改变。 设计及其代码实现会不停地发展和变化。
设计可以分为两层:战略和战术。 前期的设计属于战略,通常只有在没有深入理解需求的时候需要这样的设计。更确切的说,它应该 只描述总体战略,不应深入到具体的细节。
 
12 合理地使用技术
“你开始了一个新的项目,在你面前有一长串关于新技术和应用框架的列表。这些都是好东西,你真的需要使用列表中所有的技术。想一想,你的简历上将留下漂亮的一笔,用那些伟大的框架,你的新应用将具有极高的技术含量。”
这个技术框架真能解决这个问题么?(如果需要, 先做一个小的原型)
你将会被它拴住么?(一些技术是贼船,一旦你使用了它,就会被它套牢,再也不可能回头了。我们需要 考虑它是开放技术还是专利技术)
维护成本是多少?(维护成本昂贵。我们听说,有个项目的合同是支持一个规则引擎,引擎一年的维护费用是5万美元,但是,这个数据库只有30条规则)
不需开发你能下载到的东西。新技术就应该像是新的工具,可以帮助你更好地工作,它自己不应该成为你的工作。
 
13 保持可发布
“我们刚试用的时候发现了一个问题,你需要立即修复它,放下你手头的工作,去修复那个刚发现的问题。不用告诉其他任何人—赶快让它工作就行了。”
已提交的代码应该随时可以行动。
在本地运行测试;检出最新的代码;提交代码。
 
14 提早集成,频繁集成
“只要没有到开发的末尾阶段,就不要过早地浪费时间去想如何集成你的代码,至少也要等开发差不多的时候,才可以考虑它。”
敏捷的一个主要特点就是 持续开发,而不是三天打鱼两天晒网地工作。特别是在几个人一起开发同一个功能时,更 应该频繁地集成代码。 绝不要做大爆炸似的集成。
代码集成是主要的风险来源。要想规避这个风险,只有提早集成,持续而有规律地进行集成。
 
15 提早实现自动化部署
“没问题,可以手动安装产品,尤其是给质量保证人员安装。”
系统能在你的机器上运行,或者能在开发者和测试人员的机器上运行,当然很好,但是,它同时也 需要能够部署在用户的机器上。
质量保证人员应该测试部署过程。
从第一天起就开始交付, 一开始就实现自动化部署应用。
如果维护安装脚本变得很困难,那很可能是一个早期警告,预示着—很高的维护成本。
 
16 使用演示获得频繁反馈
“客户不停的更改需求,导致我们严重地延期。他们一次就应该想清楚所有想要的东西,然后把这些需求给我们。”
需求就像是流动着的油墨。 你无法冻结需求,就像你无法冻结市场、竞争、知识、进化或者成长一样。就算你真的冻结了,也很可能是冻结了错的东西。
不一致的术语是导致需求误解的一个主要原因。所以,需要 维护一份项目术语表。人们应该可以公开访问它,一般是在wiki或内部网里。
项目启动了一段时间以后,你就应该进入一种舒适的状态, 团队和客户建立了一种健康的富有创造性的关系。
 
17 使用短迭代,增量发布
“我们为后面的3年制定了漂亮的项目计划,列出了所有的任务和可交付的时间表。只要我们那时候发布了产品,就可以占领市场”
给我一份详细的长期报告,我就会给你一个注定完蛋的项目。
对于大项目,最理想的办法就是小步前进,这也是敏捷方法的核心。大步跳跃大大地增加了风险,小步前进才可以帮助你很好地把握平衡。
 
18 固定的价格就意味着背叛承诺
“对这个项目,我们必须要有固定的报价。虽然我们还不清楚项目的具体情况,但仍要有一个报价。”
固定价格的合同会是敏捷团队的一大难题。我们一直在谈论如何用持续、迭代和增量的方式工作。但是现在却有些人跑过来,想提早知道它会花费多少时间及多少成本。
软件项目天生就是变化无常的,不可重复。如果要提前给出一个固定的价格,就几乎肯定不能遵守开发上的承诺。
如果你现在别无选择,你不得不提供一个固定价格,那么你 需要学到真正好的评估技巧。
 
19 守护天使
“你不必为单元测试花费那么多时间和精力。它只会拖延项目的进度。好歹,你也是一个不错的程序员—单元测试只会浪费时间。”
单元测试能 及时提供反馈
单元测试让你的 代码更加健壮
单元测试时有用的 设计工具
单元测试是你 自信的后台
单元测试是 可信的文档
单元测试是 学习工具
 
20 先用它再实现它
“前进,先完成所有的库代码。后面会有大量时间看用户是如何思考的。现在只要把代码扔过墙就可以了,我保证它没有问题。”
很多成功的公司都是靠着“吃自己的狗食”活着。也就是说,如果 要让你的产品尽可能地好,自己先要积极地使用它。
编程之前,先写测试。
先写测试,你就会站在代码用户的角度来思考,而不仅仅是一个单纯的实现者,这样做是有很大区别的,你会发现因为你自己要使用它们,所以能设计一个更有用、更一致的接口。
 
21 不同环境,就有不同问题
“只要代码能在你的机器上运行就可以了,谁会去关心它是否可以在其他平台上工作,你又不用其他平台。”
一位同事的代码失败了,最终找到了罪魁祸首:一个.NET环境下的API在Windows XP和Windows2003上的行为不同。平台不同,造成了结果的不一样。
使用持久集成工具,在每一种支持的平台和环境中运行单元测试,要积极地寻找问题,而不是等问题来找你。
 
22 自动验收测试
“很好,你现在用单元测试来验证代码是否完成了你期望的行为。发给客户吧。我们很快会知道这是否是用户期望的功能。”
关键业务逻辑必须要独立进行严格的测试,并且最后需要通过用户的审批。但是,你又不可能拉着用户,逐一模块确认。所以你 需要能自动比较用户期望和实际完成的工作。
FIT(fit.c2.com),即集成测试框架,它很实用,可以更容易的 使用HTML表格定义测试用例,并比较测试结果数据。
 
23 度量真正的进度
“用自己的时间表报告工作进度。我们会用它做项目计划。不用管那些实际的工作时间,每周填满40小时就可以了。”
时间表很难真实地反映工作完成状况,因此它不可以用来进行计划、评估或表现评估。
你曾经听到开发人员报告一个任务完成了80%么?然而过了一天又一天,一周又一周,那个任务仍然是完成80%。
随意用一个比率进行度量是没有意义的。所以 不应该去计算工作量完成的百分比,而应该测定还剩下多少工作量没有完成。如果你最初估计这个任务需要 40个小时,在开发了35个小时之后,你认为还需要另外30个小时的工作。那就得到了很重要的度量结果(这里 诚实非常重要,隐瞒真相毫无意义)
关注功能,而不是日程表。
 
24 倾听用户的声音
“用户就是会抱怨。这不是你的过错,是用户太愚蠢了,连使用手册都看不懂。它不是一个bug,只是用户不明白如何使用而已。他们本应该知道更多。”
不管它是否是 产品的bug,还是 文档的bug,或者是 对用户社区理解的bug,它 都是团队的问题,而不是用户的问题。
对于一些软件,倒霉的用户必须要配置那些包含了一些魔术数字的模糊系统文件,否则系统根本不会运行。系统既没有错误提示消息,也不会崩溃,只是显示大黑屏和一个斗大的“退出”按钮。
每一个抱怨的背后都隐藏着一个事实。找出真相,修复真正的问题。
没有愚蠢的用户;只有愚蠢自大的开发人员。
“它就是这样的。”这不是一个好答案。
你的用户有可能会阅读所有的文档,记住其中的所有内容。但也可能不会。
 
25 代码要清晰地表达意图
“可以工作而且易于理解的代码当然好,但是让人觉得聪明更加重要。别人给你钱是因为你脑子好使,让我们看看你到底有多聪明。”
Hoare说“设计软件有两种方式。一种是设计得尽量简单,并且明显没有缺陷。另一种方式是设计得尽量复杂,并且没有明显的缺陷。”(Hoare创造了Algol 60编程语言,并发明了快速排序算法。于1980年获得图灵奖。)
代码阅读的次数要远远超过编写的次数,所以在编写的时候值得花点功夫让它读起来更加简单。
当开发人员们像一群旁观者见到UFO一样围在代码四周,感到恐惧、困惑与无助时,这个代码的质量就可想而知了。
看一个例子:
 
coffeeShop.PlaceOrder(2);//通过阅读代码,可以大致明白这是要在咖啡店中下一个订单。但是2代表什么意思?
coffeeShop.PlaceOrder(2 /* large cup */); //不妨添加一些注释。但注释有时候是为了帮写得不好的代码补漏。

public enum CoffeeCupSize
{
Small,
Medium,
Large
}
coffeeShop.PlaceOrder(CoffeeCupSize,Large);//如果使用上枚举值,代码就一目了然了。
 
应该让自己或团队的其他任何人,可以读懂自己一年前写的代码,而且只读一遍就知道它的运行机制。
 
26 用代码沟通
“精确地解释代码做了什么,每行代码都要加注释。不用管为什么要这样编码,只要告诉我们做了什么就好了。”
源代码可以读懂,不是因为其中的注释,而应该是由于它本身优雅而清晰。
要尽量 避免使用神秘的变量名。(i常用于循环索引变量,str常用于表示字符串。如果用str表示循环索引变量,可真不是好主意)
在代码 可以明确传递意图的地方,不要使用注释。
解释 代码做了什么的注释用处不那么大。相反, 注释要说明为什么会这样写代码。
 
27 动态评估取舍
“性能、生产力、优雅、成本以及上市时间,在软件开发过程中都是至关重要的因素。每一项都必须达到最理想的状态。”
与其花费时间去提升千分之一的性能表现,也许减少开发投入,降低成本,并尽快让应用程序上市销售更有价值。
如果现在投入额外的资源和精力,是为了将来可能得到的好处,要 确认投入一定要得到回报。( 大部分情况下,是不会有回报的)
 
28 增量式编程
“真正的程序员写起代码来,一干就是几个小时,根本不停,甚至连头都不抬。不要停下来去编译你的代码,只要一直往下写就好了!”
如果不对自己编写的代码进行测试,保证没有问题,就不要连续几个小时,甚至连续几分钟进行编程。相反, 应该采用增量式的编程方式。
采用增量式编程和测试,会倾向于创建更小的方法和更具内聚性的类。你应该 经常评估代码质量,并不时的进行许多小调整,而不是一次修改许多东西。
在写了几行代码之后,你会迫切地希望进行一次构建/测试。在没有得到反馈时,你不要走的太远。
 
29 保持简单
“通过编写史上最复杂的程序,你将会得到美誉和认可,更不用提保住你的工作了。”
Andy曾经认识一个家伙,他对设计模式非常着迷,想把它们全都用起来。有一次,要写一个大概几百行的代码程序。在被别人发现之前,他已经成功将17种设计模式,都运用到那可怜的程序中了。——这不应该是编写敏捷代码的方式。
问题在于, 许多开发人员倾向于将投入的努力与程序复杂性混同起来。如果你看到别人给出的解决方案,并评价说“非常简单且易于理解”,很有可能你会让设计者不高兴。许多开发人员以自己程序的复杂性为荣,如果能听到“Wow,这很难,一定是花了很多时间和精力才做出来的吧。” 这时,他们就会面带自豪的微笑了。 其实应当恰恰相反,开发人员更应该为自己能够创建出一个简单并且可用的设计而骄傲。
简单不是简陋。
 
30 编写内聚的代码
“你要编写一些新的代码,看看IDE中现在打开的是哪个类,就直接加进去吧。如果所有的代码都在一个类或组件里面,要找起来是很方便的。”
内聚性用来评估一个组建(包、模块或配件)中成员的功能相关性。内聚程度高,表明各个成员共同完成了一个功能特性或是一组功能特性。内聚程度低的话,表明各个成员提供的功能是互不相干的。
类也要遵循内聚性。如果一个类的方法和属性共同完成了一个功能,这个类就是内聚的。
不过, 不要把一些东西分成很多微小的部分,而使其失去了实用价值。当你需要一只袜子的时候,一盒棉线不能带给你任何帮助。
 
31 告知,不要询问
“不要相信其他的对象。从别人那里去拿你需要的信息,然后自己处理,自己决策。不要放弃控制别人的机会”。
告知=命令,询问=查询
命令和查询相分离模式,就是要将功能和方法分为命令和查询两类,并在源码中记录下来,以做到将命令代码都放在一起,并将所有查询代码都放在一起。
绝对不能允许一个看起来无辜的“查询”去修改对象的状态。
 
32 根据契约进行替换
“深层次的集成是很棒的。如果你需要其他类的函数,直接继承它们就好了!”
保持系统灵活性的关键方式,是当新代码取代原有代码之后,其他已有的代码不会意识到任何差别。
如果你不确定一个接口做出了什么样的承诺,或者有什么样的需求,那就很难提供一个对其有意义的实现了。
 
33 记录问题解决日志
“在开发过程中是不是经常遇到似曾相识的问题?这没关系,以前解决过的问题,现在还是可以解决掉的。”
面对问题是开发人员的一种生活方式。 当问题发生时,我们会希望记起第一次是如何解决的,而且希望下次能够更快地把它搞定。但是,有时我们又记不清上次是如何修复的了。
不要在同一处跌倒两次。
要想得到更好的效果,不妨维护一个保存曾遇到的问题以及对应解决方案的日志,我们称之为每日日志(daylog)。
可以选择符合需求的任何格式,下面的内容可能用得上:

       问题发生日期
        问题简述
        解决方案详细描述
        引用文章或网址,以提供更多细节或相关信息

    任何代码片段、设置或对话框的截屏

只要它们是解决方案的一部分,或者可以帮助更深入地理解相关细节即可记入日志。 务必要将上述信息变为计算机可搜索的格式。
 
34 警告就是错误
“编译器的警告信息只不过是给过分小心和过于书呆子气的人看的。它们只是警告而已。”
有些警告是过于挑剔的编译器的良性副产品,但有些则不是。例如,一个关于未被使用的变量的警告,可能不会产生什么恶劣影响,但却 有可能是暗示某些变量被错误使用了。
签入带有警告的代码,就跟签入有错误或者没有通过测试的代码一样,都是极差的做法。
 
35 对问题各个击破
“要调试一个明显的错误,只要去查看整个系统的代码,而且是要全部过一遍。毕竟你不知道问题可能发生在什么地方,这样做是找到它的唯一方式。”
单元测试带来的积极效应是它会强迫形成代码的分层。要保证代码可测试,就必须把它从周边代码中解脱出来。
认识复杂问题的第一步,是将它们分离出来。
很多应用的代码在编写时没有注意到这一点,使得分离变得特别困难。应用的各个构件部分之间会彼此纠结:想把这个部分单独拿出来,其他的会紧随而至。在这些状况下,最好花一些时间把关注的代码提取出来,而且创建一个可让其工作的测试环境。
 
36 报告所有的异常
“不要让程序的调试者看到那些奇怪的异常。处理它们是你的责任。把你调用的一切都包起来,然后发送自己定义的异常。”
作者曾经使用一个非常流行的开源程序库时倍受打击。作者调用的一个方法本来应该创建一个对象,可得到的却是null,调查很久都没有头绪。幸好这个库是开源的,所以他下载了源代码,并找到了出问题的那个调用方法。那个方法认为她的系统中缺少了某些必要的组件。这个底层方法抛出了带有相关信息的异常。但是,上层方法却偷偷地用没有异常处理代码的空catch代码块,把异常给忽略掉了,然后抛出了一个null。后来,作者安装了相应的组件,问题解决了。
 
37 提供有用的错误信息
“不要吓着用户,吓程序员也不行,要提供给他们干净整洁的错误信息。”
在设计一个登陆页面时,当用户输错密码时,我们提示哪个信息更好呢:“Unable to perform operation”、“Couldn’t login…”、还是“Error validating password”
错误信息有助于问题的解决。当问题发生时,可以详细研究问题的细节描述和发生上下文。
 
38 定期安排会面时间
“会议安排得越多越好。实际上,我们要安排更多的会议。”
立会 (站着开的会议,Scrum最早引入并被极限编程所强调的一个实践)是将团队召集在一起,并让每个人了解当下进展状况的好办法。顾名思义,参与者们不允许在立会中就坐,这可以保证会议快速进行。一个人坐下来之后,会由于感到舒适而让会议持续更长的时间。
要保证立会议题不发散,每个人只能回答下述三个问题:
    昨天的收获是什么
    今天计划要做哪些工作
    面临着哪些障碍
大家都期盼着立会,希望彼此了解各自的进度和手上的工作,而且不怕把各自遇到的问题拿出来公开讨论。
 
39 架构师必须写代码
“我们的专家级架构师会提供设计好的架构,供你编写代码。他经验丰富,拿的薪水很高,所以不要用一些愚蠢的问题或者实现上的难点来浪费他的时间。”
这些架构师通常在项目开始时介入,绘制各种各样的设计图,然后在重要的代码实现开始之前离开。有太多这种“Powerpoint架构师”。由于得不到反馈,而且设计会随着时间而演进,所以他们的架构设计工作也不会有很好的收效。
新系统的设计者必须要亲自投入到实现中去。
 
40 实行代码集体所有制
“不用担心那些烦人的bug,Joe下周假期结束回来后会把它解决掉的。在此之前先想个权宜之计应付一下吧。”
不应像国家宣称对领土的所有权一样,声明个人对代码的所有权。任何一位团队成员,重要理解某段代码的来龙去脉,就应该可以对其进行处理。如果某一段代码只有一位开发人员能够处理,项目的风险无形中也就增加了。
相比找出谁的主意最好、谁的代码实现最烂而言, 解决问题,并让应用满足用户的期望更为重要。
在大型项目中,如果每个人都可以随意改变任何代码,一定会把项目弄得一团糟。代码集体所有制并不意味着可以随心所欲、到处破坏。
————————————————
版权声明:本文为CSDN博主「笑尘醉梦」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_43382960/article/details/105109560

更多好习惯

拥抱unix哲学

每个程序员入门的第一堂和第二堂课应该是和unix哲学相关的内容,简言之就是:做一件事,做好它。具体点:

  • 小即是美。
  • 让程序只做好一件事。
  • 尽可能早地创建原型。
  • 可移植性比效率更重要。
  • 数据应该保存为文本文件。
  • 尽可能地榨取软件的全部价值。
  • 使用shell脚本来提高效率和可移植性。
  • 避免使用可定制性低下的用户界面。
  • 所有程序都是数据的过滤器。

再具体一些(TL;DR):

In [1]: import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

选一个样板,follow之

每个NBA新秀都有自己的样板,我们也总习惯称某足球新星为『小罗』,『小小罗』。样板为你提供了可模仿可追赶的对象,同时也让你审视自己究竟想成为什么样的程序员。我的样板是Greg Pass和Werner Vogels,虽然我这辈子可能也达不到他们的高度,可这并不妨碍向着我心目中的明星一步步靠近。

写代码,而不是调代码

写软件最糟糕的体验恐怕是边写边调,写一点,运行一下,再写一点。是很多程序员都会这么干。原因有二:1. 不熟悉相关的代码(类库),需要边写边运行保证代码的正确。2. 现代编程语言的REPL(Read-Evaluate-Print-Loop,就是语言的shell)能力助长了这一行为。

写系统软件的人很少这么做。他们手头糟糕的工具让边写边调的行为成为效率杀手 —— 如果稍稍改动,编译就要花去几分钟,甚至更长的时间,你还会这么干么?所以他们往往是写完一个模块,再编译调试。(由此看来,高效的工具有时候是把双刃剑啊)

我觉得写代码就跟写文章一样,构思好,有了大纲,就应该行云流水一样写下去,一气呵成,然后回过头来再调整语句,修改错别字。如果写完一段,就要回溯检查之前写的内容,效率很低,思维也会被打散。

靠边写边调做出来的代码还往往质量不高。虽然局部经过了雕琢,但整体上不那么协调,看着总是别扭。这就好比雕刻,拿着一块石头,你先是精修了鼻子,然后再一点一点刻画面部。等修到耳朵的时候,鼻子可能过大或过小,即便再精美,它也得不到赞赏。

聪明地调试

软件总会出问题。遇到问题,很多程序员就会用IDE在各种可能的地方加断点调试,如果没有IDE,那么各种print/log手段一齐抛出,有枣没枣打一杆子再说。

优秀的程序员会在撰写代码的时候就考虑到调试问题,在系统关键的节点上注入各种等级的调试信息,然后在需要的时候打开相应的调试级别,顺藤摸瓜,避免了不靠谱的臆测。这是调试之『道』。

很多问题打开调试开关后就原形毕露,但有时候靠调试信息找到了初步原因,进一步定位问题还需要具体的工具,也就是调试之『术』,如上文所述之断点调试。有些时候,遇到靠类似gdb(如python的pdb)的工具无法解决的问题时(如性能问题),你还需要更多的调试工具做runtime profiling,如systemtap。

使用标记语言来写文档,而非word/power point

不要使用只能使用特定软件才能打开的工具写文档,如word/page或者power point/keynote。要使用『放之四海而皆可用』的工具。

java的市场口号是:『一次编写,到处运行』,对于文档,你也需要这样的工具。Markdown(md) / Restructured Text(rst)(以及任何编辑语言,甚至是jade)就是这样的工具。通过使用一种特定的文本格式,你的文档可以被编译成几乎任意格式(html,rtf,latex,pdf,epub,...),真正达到了『一次编写,到处运行』。最重要的是,由于逻辑层(文章本身)和表现层(各种格式,字体,行距等)分离,同样的文档,换个模板,就有完全不一样的形象。

除非必须,我现在所有的文档都是md或者rst格式。

一切皆项目

程序员的所有产出应该项目制。软件自不必说,文档和各种碎片思想也要根据相关性组织成项目。举一些我自己的例子:

  • 我的博客是一个名叫jobs的github项目
  • 我的微信文章全部放在craftsman这个项目中
  • 我学习某种知识的过程(比如说golang)会放在一个或若干个项目中
  • 我工作上每个项目的各种产出(包括会议纪要)会按照项目对应生成git repo

项目制的好处是具备可回溯性。每个项目我可以用git来管理,这样,几乎在任何一台设备上我都可以看到我之前的工作。想想你三年前写的某个文档,你还能找到它么?你还能找回你的修改历史么?

项目制的另一大好处是可以在其之上使能工具。比如说你看到的这些微信文章,我随时可以

make publish YEAR=2014

来生成包含了2014年我所写文章的pdf。

心态开放,勇于尝试

在程序员社区里,语言之争,系统之争,软件思想之争几乎是常态。python vs ruby,go vs java vs erlang vs rust,scala vs cljure,OOP vs FP,iOS vs Android。其实不管黑猫白猫,抓到老鼠的就是好猫,facebook还用php呢。程序员应该用开放的心态去包容新的技术,新的思想,勇于尝试,而不是立即否定。这个世界最悲哀的是,手里有把锤子,看什么都是钉子(或者说,眼里就只能看见钉子)。

我接触mac时间不过三年。可这三年时间,我从对mac不屑,到深深热爱,最终成为mac的一个重度用户。很多东西用过才知道,不尝试不接触我可能永远活在自己下意识构筑的无形之墙的另一边。

最近的两年里我学习了erlang,golang,scala,还看了一点点clojure和rust。目前我热衷于golang开发,但并不妨碍我继续拥抱python和nodejs。每个程序员要在不同的层级上有一门主力语言,比如说我:

  • 系统级(realtime):C (可能以后会是rust)
  • 系统应用级(realtime):erlang(养成中)
  • 系统应用级(非realtime):golang(养成中)
  • 应用级:python
  • Web后端:python,nodejs,golang
  • Web前端:javascript
  • 设备端:Android Java(暂无计划)

这个列表你不必参考,我只是想用此来说明心态越开放,你看到的世界就越大。

如果你对本文感兴趣,欢迎订阅公众号『程序人生』(搜索微信号 programmer_life)。每天一篇原汁原味的文章,早8点与您相会。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值