程序员修炼之道 阅读笔记

本文是程序员修炼之道的阅读笔记和自己的经历以及思考

  • 提供各种选择,不要找蹩脚的借口

    如果你犯错了,那么勇敢的承认它,并且承担后果,而不是找各式各样的借口或者撒谎.如果从一开始就判定 当前的做法可能会有问题,那么应该提出来,并且拒绝为此承担后果,当然,同时应当提供更多的,更好的选择.

  • 不要容忍破窗户

    “这代码太搓了,看都不想看到它”, “算了,等有空的时候再来修一下吧” — 错. 一旦发现破窗户,我们应该 立即修掉它,而不是让他继续留着.在日常的软件开发中我们肯定有过类似的想法,但最后的实践证明,几乎不会 再去修.甚至 “TODO = never do”,所以如果我们发现了破窗,或者是闻到了代码的坏味道,应当立即修掉他. 整个项目都是烂的,怎么办?重构或者跳槽.

  • 要做变化的催化剂

  • 记住大背景

    每个人都会想,这破玩意儿都这么破了,懒得改,我只要维护好我自己的那一部分就好了.但事实上,也许维护 自己那一部分代码的时候又会这么想:反正大家都写的那么烂,我这里也不用太讲究.如此恶性循环下去,整个 项目就会垮掉.所以我们应当主动承担起带动变化的角色.

    - 首先要坚决维护好自己(一个人)开发的项目
    - 然后要在发现大项目中的坏味道的时候除掉他
    - 至于大背景,则是首先你要确定你所做的对项目是真正有益的
    
  • 使质量成为需求问题

    代码不可能完美,日常的编程中,总是把质量权衡在某个度上,因为,优化是无止境的.当然,这并不意味着写出 质量低下的代码是可以理解和原谅的(所以这个度其实很难把控).

  • 定期为你的只是资产投资

    程序员所学的知识其实同样也有时间价值 — 和金融资产一样. — 有的知识从出生到现在都没有过时,例 如学习UNIX相关的知识,有的知识火一阵子就开始走下坡路.

    - 定期投资
    - 多元化投资 --- 不要把你所有的技术都放在一个篮子里,首先从你所在项目使用到的技术了解起,例如
    如果是web开发项目,你所需要知道的知识可能有:HTTP协议,HTML/CSS/JS,熟悉所使用的框架,RPC和JSON,
    关系型数据库和ORM,缓存和CDN,负载均衡/单点故障,异步任务,事务,数据库扩展,测试/自动化测试等.
    当你了解了这些之后,再去寻找更多的知识.
    - 管理风险 --- 像投资一样,不能总是追求新兴的东西,但是也不能太过于保守.
    - 低买高卖 --- 如果你看好一门新出的技术,那么就应该立即学习它,就像在一只你看好的股票刚出的
    时候就买入
    - 重新评估和平衡 --- 你需要定期的评估,目前所掌握的知识,有哪些需要刷新一下自己的"缓存",是不
    是有哪些新的知识需要去了解一下
    

    可以为自己设定一系列目标,例如:

    - 每年至少学习一种新语言, 这点我做的还不够好 --- 2015-2017上半年这段时间一直都在用Python,
    2017年下半年开始才接触Golang,之后会计划的更好(当然,此前接触的C/C++/Java等都忘了,所以不能算)
    - 每季度阅读一本技术书籍, 这点我做的比较好,每天我都会看一点书,技术有关或无关,但每季度绝对
    不止读一本
    - 也要读非技术书籍,这点做的不够好,2017年之前几乎都是只读技术书籍,2017年之后才开始改变
    - 上课,这点做的不够好,我几乎不去本地的大学上课,因为比较麻烦...不过我会看一些公开课
    - 参加本地组织,这点我做的很不好,几乎不去,主要是参加过几次,觉得太水了,很无聊
    - 试验不同的环境,嗯,Windows和Linux我都用,不过,前者娱乐后者工作.IDE极少用.
    - 跟上潮流,这点我得说,目前没有这样的计划,因为毕业的前几年,给自己定的计划是打造扎实的基础
    - 上网,我天天上...
    
  • 批判的分析你读到的和你听到的

    自然,所有人嘴里说出来的都会加以粉饰,你看到的也未必就是事实.在高中的时候我明白了这个道理,所以 给自己的签名一直都是”你的眼睛能看多远”.看一门技术也是如此,批判的看,看到优点,也要看到缺点,知道 什么情况下是最佳使用场景,什么时候不适合.

    然而我必须承认,要做到非常准确的识别事实,很难 — 要不然我就不会买错一堆书了,目前get到的买书技能:

    - 上评分网看看网民的评论,但是当心,可能是刷出来的,也可能你并没有和他们处在同一个阶段.
    - 问你身边爱读书,读过很多书的人,求他们给予推荐
    
  • 你说什么和你怎么说同样重要

    我一直认为程序员非常重要的三个能力:硬实力,沟通能力和抽象能力. 记住程序是为人服务的,你最终的沟通 对象是人 — 产品经理或者客户. 你要考虑你的听众是不是听得懂,你可以跟程序员说术语,但是不要跟他们 说术语,不是所有人都知道一切的,你也不知道世界上的一切.其实道理很简单,设身处地站在别人的角度上考虑 一下就好.

  • DRY原则 — Don’t Repeat Yourself.

    不要到处复制粘贴,要不然改起来你就知道了,我的个乖乖,会累死的.把重复的代码和逻辑抽象抽离出来,变成 工具函数(utils)或者类内方法,或者服务类(service),或者微服务等.总而言之,不要重复.

    • 强加的重复: 你大概不会想看到 i += 1后面有注释告诉你这是把i的值加一然后重新赋值给i吧
    • 无意的重复: 例如一个人有FirstName和LastName,那么如果存储了FullName,就会是一种重复
    • 无耐性的重复: 复制粘贴???看起来是很快,改起来你就知道有多痛苦了.幻想着我这里极少可能性会改. 我只能说,别忘了,还有墨菲定律呢!
    • 开发者之间的重复: 我现在所开发的系统里, 不同的部门之间数据库就存着同一套系统不同的编码, 你知道 这有多痛苦吗? :cry:
  • 让复用变得容易

  • 消除无关事物之间的影响

    关于这两点,我们听到的最多的词语大概是:高内聚,低耦合;针对接口编程等.微服务最近这么火爆,我个人认为 归功于它的特点 — 强制解耦. 不再是到处都是错综复杂的import然后函数调用,每个子系统维护自己的小 领域就好.同时也就降低了自身的复杂性.

    时刻想到,如果我们改了这里,会有几个地方受到影响?正交系统给出的答案应该是一个.

    KISS原则也是和这个有关系的, Keep it simple, stupid.

  • 不存在最终决策

  • 用曳光弹找到目标

    在现实编程过程中,我们总是要对需求作出一定范围内的界定,以及,假设.假如不这么做的话,需求根本无边 无界,完成不了.但是,与之相悖的,我们的假设做的越多,那么抽象程度就越低,可移植能力就越差.因此,对于 做假设这件事情,只能说我们要做到”谨慎且大胆”.

    但是对于一个从来没有做过的大型的系统,应该快速出一个最小的可用的系统然后开始完善而不是无止境的 定好文档等.这样我们能尽早得到反馈,同时也能让客户安心.这和快速出原型很类似,区别在于,如果我们说 快速出原型,那么这个原型很可能会被我们丢弃.

  • 为了学习而制作原型

    制作原型,是为了快速体验一下既定方案,从而从中体验到这种方案的优缺点,利弊等.不过通常原型都很丑陋, 因为它只是原型而已.

  • 靠近问题领域编程

    DSL很强大,但是对使用它的用户也会有要求.日常很少用到.

  • 估算,以避免发生意外

  • 通过代码对进度表进行迭代

    估算,我们日常中很多时候都会遇到这种问题,比如你汇报给上级,这个任务你需要多久来完成. 我们进行估算, 然后,用现实结果来评判它, 并且吸取经验, 在下一次估算的时候用上它, 那么我们的估算将会越来越准确.

    书中给了我们一种万能回复: “我等会儿回答你” :).

  • 用纯文本保存知识

  • 利用命令行的力量

  • 用好一种编辑器

    你懂的 :)

  • 总是使用源码控制

    吃过亏你就知道你需要这个

  • 要修正bug,而不是发出指责

  • 不要恐慌

  • “select”没有问题

  • 不要假定,要证明

    尽管我们会发出吐槽,但是我们会修复这个问题.

    修bug要冷静,理性的分析. 而不是胡乱猜测乱碰乱撞.

    常见的调试方式:

    • 找办法复现bug
    • 首先应当怀疑自己写的代码 — 而不是编译器,OS等
    • 打印栈
    • 打印日志
    • 单步跟踪
    • 向别人/小黄鸭讲你的代码思路
  • 学习一种文本文本操作语言

    其实web开发就是文本操纵…

    学习Python和Shell吧

  • 编写能编写代码的代码

    如果说通过编写代码来生成代码,我一般都不太赞成,生成的代码通常意味着重复的,meaning-less的.我相信会有更好的办法来解决. 但是如果是从一种代码转换到另一种代码,我是支持的,例如我很喜欢的一个工具:pandoc. 我就用它把Markdown转换成网页或者是pdf.

  • 你不可能写出完美的软件

    so it is.

  • 通过合约进行设计

  • 早崩溃

    编译过程中的检查其实就是这么一回事儿,早点帮你检查出来总归比上线之后崩溃更好.

  • 如果它不可能发生,用断言确保它不会发生

    注意前提,如果它不可能发生. 也就是说, 千万千万千万不要用断言替代错误处理!

  • 将异常用于异常的问题

    不要滥用异常

  • 要有始有终

    记住自己关闭打开的文件啦,释放申请的内存啦… 这点来说,Golang的defer是个好东西, Python的with(这个context manager)也 是个好东西

  • 使模块之间的耦合减至最少

  • 要配置,不要集成

  • 把抽象放进代码,细节放进元数据

    使用配置文件而不是写死在代码里,会让软件获得更大的灵活性,比如MySQL Server提供了各式各样的参数,让用户得以控制Server的 表现和资源占用等.

    让应用变成可配置的,就可以获得最大的灵活性.

  • 分析工作流,改善并发性

    不要对流程发生的前后顺序做太多假设,而应该看是否有地方可以并发.

  • 用服务进行设计

  • 总是为并发进行设计

    总是要考虑,这一段代码是否线程安全?是否可重入?如果能满足并发安全,那么单线程执行也会很安全.

  • 使视图与模型分离

    MVC在今天应当是大行其道,背后原因就在于,把视图中的无关部分抽象出来,得以解耦和重用代码.

  • 用黑板协调工作流

  • 不要靠巧合编程

    我对自己的要求一直都是,自己写下的每一行代码,都需要知道它背后发生了什么.你要知道自己在做什么,软件是怎么跑起来的,而不是 碰巧跑起来了.

  • 估算你的算法的阶

  • 测试你的估算

    if i in ("hello", "world", "this", "is", "a", "string")if i in set(["hello", "world", "this", "is", "a", "string"]) 的效率有什么区别?

    心中有估计之后,要去验证这个估算是否是正确的,并且将验证结果加入自己的反馈系统中.

  • 早重构,常重构

    等你发现项目已经大到改不动了…那时候重构就很麻烦了.

  • 为测试而设计

  • 测试你的软件,否则你的用户就得测试

    这应当是和测试驱动开发类似的思想. 实际上测试是个好东西,只不过有时候写测试确实挺烦的…但是,如果我们经常要作出改动, 那么测试是一件非常好的事情,可以帮助我们省去重复的手工测试,可以帮助我们保证兼容性等.

  • 不要使用你不理解的向导代码

  • 不要搜集需求—挖掘它们

  • 与用户一同工作,这样才能像用户一样思考

    确实,真正的弄清楚需求非常重要,要不然迟早要被坑的.可以跟有信用的产品经理一一确定自己理解的需求是否完全对了,并且明确 告知对方不会有改动的机会 — 你知道的,不能培养他们想改就改的习惯.

    但是这里也有一个陷阱,就是有些人喜欢把所有的细节都弄清楚,然后再开始动手.做不到的,不要过度陷入细节.

  • 抽象比细节活得更长久

  • 使用项目词汇表

    这样就能让跟多人更容易沟通吧,不过我没有用过…

  • 不要在盒子外面思考 — 要找到盒子

    面对棘手的问题时,列出所有的可能的途径,然后逐一检查列表中的每一项,然后想为什么不能用某个特定的途径,真的吗?证明一下. 在思考难题的时候,更不能做过多的假设,现有假设也应该逐一检查.

  • 倾听反复出现的疑惑 — 等你准备好再开始

  • 有些事情,do it比describe it更好

  • 不要做形式方法的奴隶

  • 围绕功能,而不是工作职务进行组织

    我一直认为,不要拘泥于形式,而要理解真正的内涵.就像敏捷开发,并不要一步一步完全遵循步骤,而理解其真正内涵才是最重要的.

  • 昂贵的工具不一定能制作出更好的设计

    其实设计是否良好,还是取决与设计者的品味

  • 不要使用手工流程

  • 早测试,常测试,自动测试

  • 要通过全部测试,编码才算完成

  • 通过”蓄意破坏”测试你的测试

  • 测试覆盖状态,而不是代码覆盖

    自动化测试啊哥!千万不要手动点点点…

    • 单元测试
    • 集成测试
    • 边界测试
    • 验证和校验
    • 性能测试
    • 回归测试
    • 可用性测试
    • 资源耗尽,错误及恢复
  • 一个bug只抓一次

    找到一个bug,修复之后记得补上一些测试,这样如果下次再出现,就可以在自动化测试中发现. 而不是修完之后就想,好了,修好了,下 次不会在出现了.

  • 把英语当作另一种编程语言

  • 把文档放在代码里,而不是代码外

  • 温和的超出用户的期望

  • 在你的作品上签名

    实际上,版本控制工具已经帮你干了这个事情了. 当然原作是指,可以通过增加自豪感而增加责任感.


更多文章
  • Grafana Gravatar头像显示bug修复
  • flutter中使用RESTful接口
  • Vim YouCompleteMe使用LSP(以dart为例)
  • flutter webview加载时显示进度
  • SQLAlchemy快速更新或插入对象
  • 修复Linux下curl等无法使用letsencrypt证书
  • 欣赏一下K&R两位大神的代码
  • MySQL的ON DUPLICATE KEY UPDATE语句
  • 使用microk8s快速搭建k8s
  • Python中优雅的处理文件路径
  • Go语言MySQL时区问题
  • 我的技术栈选型
  • 为什么我要用Linux作为桌面?
  • disqus获取评论时忽略query string
  • MySQL性能优化指南