程序员不得不读的书前二就是
《程序员修炼之道》和《代码大全》
大学时曾读过《程序员修炼之道》,最近换工作转正答辩前要求重新读此书
以下是精华提炼,和个人总结
对于我们的缺点—还有我们的无知和我们的错误—我们必须诚实
正确认识已经发生的错误,对自己的职业生涯负责。对于已经发生的错误,重要的是如何处理来挽回局面,这样也可以赢得别人的帮助
正确认识已经发生的错误,对自己的职业生涯负责。对于已经发生的错误,重要的是如何处理来挽回局面,这样也可以赢得别人的帮助
这点在接手项目的时候最为明显。往往好的项目让人不忍心去破坏其中完美的逻辑和美好的语言。一旦自己开始利用混乱的逻辑和糟糕的代码,往后的编码质量往往直线下滑。
做变化的催化剂;记住大图景
拖延,规范,要时刻提醒。设计出合理的东西,然后拿出他,这就是石头。
使质量成为需求问题
质量一般都是隐含的需求。但也不要过分追求质量而停止脚步。停滞的结果往往就是自己都失去耐心。
定期为你的知识资产投资
你说什么和你怎么说同样重要
多问,多说。态度很重要。
DRY—Don’t Repeat Yourself 不要重复你自己;让复用变得容易
代码的重复,往往是由于经受不住诱惑而直接拷贝。抽取是一个好办法,抽取与重构应该自主的进行。结合上一章, 想清楚哪些以后可以重复使用,或者在工作完成之后对代码进行重构抽取出可以重复利用的部分。当然,这些都需要一定的功力。做好设计。
开发者的重复往往是由于相互之间缺乏沟通,但目前来看貌似在项目管理软件下,这种情况发生的比较少,往往在共同修改某些小功能上容易发生。
消除无关事物之间的影响
其实主要说的就是减少模块之间的耦合性。包括在设计的时候,选择技术的时候。目前各种框架的使用很好的减少了前台与后端之间的耦合性,但在工作中仍旧会发现某些代码之间嵌套的很死,耦合性很差。注意保持解耦,减少全局变量,并写好相关文档。
另外在做习题的时候发现面向对象由于多态,继承等不同于面向过程语言的一些特性,似乎更容易发生耦合现象。这个tip还需要在以后工作中持续思考。
不存在最终决策
这个tip是个启发。没有最终决策不等同于可以随意改变最初的需求文档。需求一旦定死即可不更改,但实现的方式可以是多种多样,在实现过程中寻求最优,或者最便利(有时往往不是最优)的解决方案,应该在项目开发生命周期中持续进行。这应该就是同事说的“工作方法”。当然其中也应该包括程序员的自尊心,即便是做统计数据用in也不要图方便用union all(笑)。
用光弹找到目标
这里说说的应该是前期的一些实验代码,实验后有可能废弃,也可能融合在项目中保存生命力。一些小的实验代码往往可以寻求问题的解决之道,这里不要怕浪费时间,但相反也不要进入拿起来就做的状态,防止陷入做了那么多才发现自己做错了的状态。
为了学习而制作原型
这里并没有什么体会。不知道在原有项目基础上进行重新架构的项目算不算。记下来以后再看。
靠近问题领域编程
估算,以避免发生意外
这里给出一种估算的简单方式。建模,分割作为组件,给各个参数指定值,计算,验证。我认为这里是提出了一种估算项目进度的训练方式。
在被要求进行估算时说什么:我等会儿回答你
选择领域内的某一个ide,学会所有功能和快捷键,熟练掌握,并乐于潮语IDE所世家的各种限制
用纯文本保存知识
任何语言都可以操作纯文本,
使用纯文本(可以是.md) 可以在任何平台上展示
利用shell 的力量
熟练掌握各平台终端命令,熟练掌握git命令
命令行往往比gui强大,虽然平时可以使用gui,但是gui不可能给出所有使用场景,所以建议必须精通命令
用好一种编译器
vs code 与idea
注意
统一IDEA与格式化规则
进步远非由变化组成,而是取决于好记性,不能记住过去的人,被判重复过去
记住合理使用UNDO 和 TODO
总是使用源码控制
一次项目开发最好一次提交记录(rebase)这样以后排查错误,以及查看开发书会比较简洁
要修正问题而不是发出指责
bug是谁的不是最重要的,最重要的是为什么会出现,察觉潜在隐患时为什么没有重视,
不要恐慌
恐慌会让你找不到bug原因(实战有遇到)
解决bug的第一要素:复现bug。越容易复现的bug,越好修复
详细陈述涉及bug的相关逻辑,或许原因就在你的话里
不要假定,要证明
学会一种文本操纵语言
编写能编写代码的代码生成器
用来解决固定且简单重复的场景
你不可能写出完美的软件
没有人能写出完美的软件
通过合约进行设计
DBC 按合约设计
死程序不会说谎
如果有一个常见错误,意味着可能有很多错误。
如果它不可能发生,用断言确保它不会发生
如果它不可能发生,用断言确保它不会发生
将异常用于异常问题
要有始有终
使用资源时用完就要换,有一个有始有终的过程
保持灵活的一种办法是尽可能保持代码精简
使模块之间的耦合减少至最低
函数的得墨忒法则
要配置不要集成
尽可能保证程序可配置,即使开发时没有配置需求,也需要可配置需求,可以使用程序开头变量配置,其次可以使用运营平台配置。
将抽象放进代码里,细节放在元数据里
元数据是关于数据的数据,元数据是任何对应用进行描述的数据—应用该怎样运行、它应该使用什么资源
(Put Abstractions in Code, Details in Metadata) 为一般情况编程,将细节放在被编译的代码库之外。
分层思想,分层设计
分析工作流,以改善并发性:
(Analyze Workflow to Improve Concurrency) 利用你的用户的工作流中的并发性。
用服务进行设计:
(Design Using Services) 根据服务——独立的、在良好定义、一致的接口之后的并发对象——进行设计。
总是为并发进行设计:
(Always Design for Concurrency) 容许并发,你将会设计出更整洁、具有更少假定的接口。
视图与模型分离:
(Separate Views form Models) 要根据模型和视图设计你的应用,从而以低廉的代码获取灵活性。
用黑板协调工作流:
(Use Blackboards to Coordinate Workflow) 用黑板协调完成不同的事实和因素,同时又使各参与方保持独立和隔离。
不要靠巧合编程:
(Don’t Program by Coincidence) 只依靠可靠的事物。注意偶发的复杂性,不要把幸运的巧合与有目的的计划混为一谈。
估计你的算法的阶:
(Estimate the Order of Your Algorithms) 在你编写代码之前,先大致估算事情需要多长时间
测试你的估计:
(Test your Estimates) 对算法的数学分析并不会告诉你每一件事情。在你的代码的目标环境中测定他的速度。
早重构,常重构:
(Refactor Early, Refactor Often) 就和你会在花园里除草、并重新布置一样,在需要时对代码进行重写、重做和重新架构。要铲除问题的根源。
为测试而设计:
(Design to Test) 在你还没有编写代码时就还是思考测试问题。
测试你的软件,否则你的用户就得测试:
(Test Your Software, or Your Users Will) 无情地测试。不要让你的用户为你查找bug。
不要使用你不理解的向导代码:
(Don’t Use Wizard Code You Don’t Understand) 向导代码可以生成大量代码。在你把它们合并进你的项目之前,确保你理解全部这些代码。
不要搜集需求——挖掘它们:
(Don’t Gather Requirements – Dig for Them) 需求很少存在于表面上。它们深深地埋藏在层层假定、误解和政治手段下面。
与用户一同工作,像用户一样思考:
(Work with a User to Think Like a User) 要了解系统实际上将如何被使用,这是最好的方法。
抽象比细节活得更长久:
(Abstractions Live Longer than Details) “投资”于抽象,而不是现实。抽象能在来自不同的现实和新技术的变化的“攻击”之下存活下去。
使用项目词汇表:
(Use a Project Glossary) 创建并维护项目中使用的专用术语和词汇的单一信息源。
不要在盒子外面思考——要找到盒子:
(Don’t Think Outside the Box – Find the Box) 在遇到不可能解决的问题时,要确定真正的约束。问问你自己:“它必须以这种方式完成吗?它真的必须完成吗?”
等你准备好在开始:
(Start When You’re Ready) 你的一生都在积累经验。不要忽视反复出现的疑虑。
对有些事情“做”胜于“描述”:
(Some Things are Better Done than Described) 不要掉进规范的旋涡——在某个时刻,你需要开始编码。
不要做形式方法的奴隶:
(Don’t Be a Slave to Formal Methods) 如果你没有把某项技术放进你的开发实践和能力的语境中,不要盲目地采用它。
昂贵的工具不一定能制作出更好的设计:
(Costly Tools Don’t produce Better Designs) 小心供应商的炒作,行业教条、以及价格标签的诱惑。要根据工具的价值判断它们。
围绕功能组织团队:
(Organize Teams Around Functionality) 不要把设计师与编码员分开,也不要把测试员与数据建模员分开。按照你构建代码的方式构建团队。
个人总结
不要按照单纯的前端后端,测试UI进行团队划分,而是按照项目和产品线进行划分
不要使用手工流程:
(Don’t Use Manual Procedures) Shell脚本或批文件会一次次地以同一顺序执行同样的指令。
个人总结
尽量借助工具去完成流程,辅助开发工具总是需要以销量为第一要义
早测试,常测试,自动测试
(Test Early. Test Often. Test Automatically) 与呆在书架上的测试计划相比,每次构建时运行的测试要有效的多。
个人总结
个人开发中,整合单个功能测试+模块测试+集成测试,一切以运行起来的程序测试为准
要通过全部测试,编码才算完成:
(Coding didn’t Done Until All the Tests Run) 就是这样。
个人总结
只有预期开发的要求全部测试通过,整个编码过程才算完成
通过“蓄意破坏”测试你的测试:
(Use Saboteurs to Test Your Testing) 在单独的软件副本上故意引用bug,以检验测试能够抓住它们。
测试状态覆盖,而不是代码覆盖:
(Test State Coverage, Not Code Coverage) 确定并测试重要的程序状态。只是测试代码行是不够的。
一个bug只抓一次:
(Find Bugs Once) 一旦测试员找到一个bug,这应该是测试员最后一次找到它。此后自动测试应该对应其进行检查。
英语就是一种编程语言:
(English is Just a Programming Language) 像你编写代码一样编写文档:遵守DIY原则、使用原数据、MVC、自动生成,等等。
把文档建在里面,不要拴在外面:
(Build Documentation In, Don’t Bolt It On) 与代码分离的文档不太可能被修整和更新。
温和地超出用户的期望:
(Gently Exceed Your Users’ Expectations) 要理解你的用户的期望,然后给他们的东西要多那么一点。
在你的作品上签名:
(Sign Your Work) 过去时代的手工艺人为能在他们的作品上签名而自豪。一夜应该如此。